diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index dbf81d1..dee99fc 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -8,6 +8,11 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: + inputs: + source_ref: + description: "Branch or tag to deploy from (default: current ref / master)" + required: false + default: "" # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: @@ -15,8 +20,6 @@ permissions: pages: write id-token: write -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: "pages" cancel-in-progress: false @@ -29,15 +32,26 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: + - name: Determine ref to checkout + id: ref + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ github.event.inputs.source_ref }}" ]; then + echo "ref=${{ github.event.inputs.source_ref }}" >> "$GITHUB_OUTPUT" + else + # default: use the ref that triggered the workflow (master on push) + echo "ref=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" + fi - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + ref: ${{ steps.ref.outputs.ref }} - name: Setup Pages uses: actions/configure-pages@v3 - name: Upload artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: # Upload entire repository path: './dist' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 diff --git a/dist/draft/favicon.png b/dist/draft/favicon.png new file mode 100644 index 0000000..962d8f3 Binary files /dev/null and b/dist/draft/favicon.png differ diff --git a/dist/draft/index.html b/dist/draft/index.html new file mode 100644 index 0000000..80871cd --- /dev/null +++ b/dist/draft/index.html @@ -0,0 +1,1019 @@ + + +
+Download OpenAPI specification:
This document outlines the API of Termino, utilized by Slevomat.cz, s.ro. to enable the sale of online bookings on Slevomat.cz and Zlavomat.sk.
+This API is used for connecting channel management (CM) and property management systems (PMS).
+This API is bi-directional, meaning both sides can request or push information to the other's API. Given that this API covers various system setups, there are multiple ways to establish communication. The synchronization of hotel structure and capacities is typically achieved by CM/PMS pushing information to Termino. A periodic pull of capacity information can also be configured, but push is preferred as it facilitates faster change propagation and reduces traffic between systems.
+Typical usage for channel managers includes:
+reservation and ping endpoints on your sidecapacities-update endpoint to push capacity changesget-hotel endpoint to retrieve the hotel structure and set up the connectionFor property management systems, the typical usage involves:
+hotel, reservation, and get-reservation endpoints. The ping endpoint is not needed because the hotel endpoint should provide the same information (whether the hotel is active or not).capacities on your side or calling the capacities-update push endpoint on Termino to deliver updates.All requests are required to communicate over HTTPS. Termino API endpoints support TLS protocol versions 1.2 and higher.
+All requests contain the property accessToken with a value assigned during the API verification process. These values identify the communicating parties - CM/PMS on one side and Termino on the other.
Both sides accept only HTTP POST. Requests and responses are sent with the Content-Type header set to application/json and a JSON body depending on the operation to be performed. Content encoding is always UTF-8.
If a message is received and processed, the HTTP response code should be 200 OK for successful results and any 4xx for unsuccessful results (the concrete error type is described in the response body).
5xx response codes indicate unexpected and internal errors, and the request can be retried without change. No specific response should be expected for server errors (JSON is not guaranteed). The response header Retry-After (if present) should be respected for retrying the request.
The type of message is determined by the URL.
+For push endpoints, the request should be repeated until it is successfully delivered to Termino. Similarly, Termino will repeat requests until they are accepted by your system. Successful delivery means either responding with success or an expected error described in the API specification.
+Date intervals are represented as objects with start and end properties, both formatted as YYYY-MM-DD. The start date is inclusive, while the end date is exclusive.
See DateInterval schema for details.
+{
+ "start": "2020-01-01",
+ "end": "2020-01-31"
+}
+
+{
+ "accessToken": "foobar",
+ // other properties
+}
+
+{
+ "success": true,
+}
+
+{
+ "error": {
+ "code": "invalid-access-token",
+ "message": "Access token not found."
+ }
+}
+
+These errors can occur on any API endpoint.
+| Code | +Description | +
|---|---|
invalid-format |
+Unparsable JSON | +
missing-value |
+A required property is missing. | +
invalid-value |
+A property has invalid format (e.g., wrong date, time, datetime, interval, URL...). | +
invalid-access-token |
+Invalid or expired access token | +
Each reservation has to have a unique ID for reference between systems. This identifier is later used in case of modification and cancellation of the reservation is needed.
+Termino will preferably assign our identifier with reservation creation, or it can accept and later use the reservation ID returned in response. Using Termino's ID simplifies recovery from communication failures (phantom reservations).
+Money amounts are represented as strings in hundredths of currency unit. Currency is represented using ISO 4217 currency codes (e.g., "CZK" for Czech crowns, "EUR" for euros). Supported currencies are CZK, PLN, EUR and HUF.
+For example, an amount of one hundred Euros and fifty cents is represented as:
+{
+ "amount": "10050",
+ "currency": "EUR"
+}
+
+Rate plan represents a sellable combination of room type, board type and other commercial conditions (cancellation policy, restrictions, etc.). Each rate plan has:
+id – partner-defined identifier (e.g. "HB", "NRF") - name – human readable name - pricingModel – defines how prices are provided in planning updates (per_room, per_person, per_occupancy)
+Rate plans are provided in:/hotel (HotelInfo.ratePlans) - push updates via /hotel-update (ratePlans) - planning data via /planning and /planning-update (RatePlanPlanning)Three pricing models are supported for receiving planning updates:
+per_room - price is set per room and nightper_person - price is set for count of persons and nightper_occupancy - price set per night and occupancy (occupancy is specified count of adults and children)Changes to API and its documentation
+reservation.children)reservation.meal)reservation.contact.email)occupations and occupations-update endpoints to be used for blockages. Use capacities instead.rooms parameter from RoomType structure. Only roomCount parameter is now needed to define room type structureroomId parameter from Occupation and Reservation structure. Only roomTypeId parameter is now needed to define occupationEndpoints on Termino side are called from PMS/CM system and mostly used to push data changes.
+If unsuccessful response is returned, the request has to be repeated until it is successfully delivered to Termino.
+Synchronization of changed reservations on the hotel side. +Usage:
+Updates of occupations in multiple hotels has to be sent in multiple requests.
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
required | Array of objects (Occupation) List of updated occupations. + |
{- "accessToken": "string",
- "hotelId": "string",
- "occupations": [
- {
- "id": "string",
- "type": "reservation",
- "status": "string",
- "roomId": "string",
- "roomTypeId": "string",
- "created": "2019-08-24T14:15:22Z",
- "term": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}
}
]
}{- "success": true
}Planning update of available capacities, booking restrictions (stop sale, closed arrival, closed departure, minimal length of stay), rateplans and prices.
+Granular updates are supported - you can include only availability, only rates, or both in the update. Similarly, rates update may include either prices or restrictions or both. Unchanged data should be omitted in the request.
+| accessToken required | string Access token to your API. + |
required | string or integer Your hotel id. + |
Array of objects (PlanningUpdate) |
{- "accessToken": "string",
- "hotelId": "string",
- "update": [
- {
- "roomTypeId": 123,
- "availability": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "availableRooms": 5
}
], - "rates": [
- {
- "ratePlanId": "HB",
- "planning": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "perRoomPrice": {
- "amount": "string",
- "currency": "string"
}, - "perPersonPriceMatrix": [
- {
- "personsCount": 2,
- "price": {
- "amount": null,
- "currency": null
}, - "stopSale": false
}
], - "perOccupancyPriceMatrix": [
- {
- "adultsCount": 2,
- "childrenCount": 1,
- "price": {
- "amount": null,
- "currency": null
}, - "stopSale": false
}
], - "restrictions": {
- "closedForArrival": false,
- "closedForDeparture": false,
- "stopSale": false,
- "minimalLengthOfStay": 1,
- "maximalLengthOfStay": 0
}
}
]
}
], - "roomTypeRestrictions": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "restrictions": {
- "closedForArrival": false,
- "closedForDeparture": false,
- "stopSale": false,
- "minimalLengthOfStay": 1,
- "maximalLengthOfStay": 0
}
}
]
}
]
}{- "success": true
}This endpoint is deprecated in favor of more powerful /planning-update. No removal is currently planned. Any new implementations should use /planning-update.
+Synchronization of changed capacities
+Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Your hotel id. + |
required | Array of objects (Capacity) List of updated capacities. + |
{- "accessToken": "string",
- "hotelId": "string",
- "capacities": [
- {
- "roomTypeId": 123,
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "availableRooms": 5
}
]
}{- "success": true
}Synchronization of changed hotel info and structure.
+Usage:
+| accessToken required | string Access token to your API. + |
required | Array of objects (Hotel) Updated hotel info. + |
Array of objects (RoomType) Updated room types. + | |
Array of objects (RatePlan) Updated rate plans. + |
{- "accessToken": "string",
- "hotel": [
- {
- "id": "123456",
- "name": "Hotel Example",
- "address": {
- "street": "Pernerova 691",
- "city": "Praha 8",
- "country": "CZ"
}
}
], - "roomTypes": [
- {
- "id": "123456",
- "name": "Double room",
- "beds": 2,
- "extraBeds": 1,
- "roomsCount": 10,
- "rooms": [
- {
- "id": "125",
- "name": "Room 125"
}
]
}
], - "ratePlans": [
- {
- "id": "HB",
- "name": "Half-board",
- "pricingModel": "per_room"
}
]
}{- "success": true
}Provides same information as /hotel endpoint, but in reversed direction. This endpoint is called by CM to load room types and rate plans created on Termino side and set up mapping.
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
{- "accessToken": "string",
- "hotelId": "string"
}{- "hotel": {
- "id": "123456",
- "name": "Hotel Example",
- "address": {
- "street": "Pernerova 691",
- "city": "Praha 8",
- "country": "CZ"
}
}, - "roomTypes": [
- {
- "id": "123456",
- "name": "Double room",
- "beds": 2,
- "extraBeds": 1,
- "roomsCount": 10,
- "rooms": [
- {
- "id": "125",
- "name": "Room 125"
}
]
}
], - "ratePlans": [
- {
- "id": "HB",
- "name": "Half-board",
- "pricingModel": "per_room"
}
]
}Partner endpoints should be implemented in your PMS/CM system and are called by Termino, either periodically or when specific action is performed (eg. new reservation, hotel connection).
+Information about hotel for connection process and structure of room types and rate plans.
+Usage:
+| accessToken required | string Access token for authorization + |
required | string or integer Your hotel id + |
{- "accessToken": "aa5ae844-051c-4d30-9c67-54b70c99b580",
- "hotelId": "123456"
}{- "hotel": {
- "id": "123456",
- "name": "Hotel Example",
- "address": {
- "street": "Pernerova 691",
- "city": "Praha 8",
- "country": "CZ"
}
}, - "roomTypes": [
- {
- "id": "123456",
- "name": "Double room",
- "beds": 2,
- "extraBeds": 1,
- "roomsCount": 10,
- "rooms": [
- {
- "id": "125",
- "name": "Room 125"
}
]
}
], - "ratePlans": [
- {
- "id": "HB",
- "name": "Half-board",
- "pricingModel": "per_room"
}
]
}This endpoint is deprecated is favor of more powerful /planning. No removal is currently planned. Any new implementations should use /planning.
+Synchronizing available rooms +Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
required | object (DateInterval) DateInterval is [start, end) – end date is exclusive. + |
Array of strings or integers Requested room type ids. When not provided, return capacities for all room types of given hotel. + |
{- "accessToken": "string",
- "hotelId": "string",
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "roomTypeIds": [
- "string"
]
}{- "capacities": [
- {
- "roomTypeId": 123,
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "availableRooms": 5
}
]
}Synchronizing available rooms, prices and booking restrictions (stop sale, closed arrival/departure, minimal length of stay) Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
required | object (DateInterval) DateInterval is [start, end) – end date is exclusive. + |
Array of strings or integers Requested room type ids. When not provided, return planning for all room types of given hotel. + |
{- "accessToken": "string",
- "hotelId": "string",
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "roomTypeIds": [
- "string"
]
}{- "planning": [
- {
- "roomTypeId": 123,
- "availability": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "availableRooms": 5
}
], - "rates": [
- {
- "ratePlanId": "HB",
- "planning": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "perRoomPrice": {
- "amount": "string",
- "currency": "string"
}, - "perPersonPriceMatrix": [
- {
- "personsCount": 2,
- "price": {
- "amount": null,
- "currency": null
}, - "stopSale": false
}
], - "perOccupancyPriceMatrix": [
- {
- "adultsCount": 2,
- "childrenCount": 1,
- "price": {
- "amount": null,
- "currency": null
}, - "stopSale": false
}
], - "restrictions": {
- "closedForArrival": false,
- "closedForDeparture": false,
- "stopSale": false,
- "minimalLengthOfStay": 1,
- "maximalLengthOfStay": 0
}
}
]
}
], - "roomTypeRestrictions": [
- {
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "restrictions": {
- "closedForArrival": false,
- "closedForDeparture": false,
- "stopSale": false,
- "minimalLengthOfStay": 1,
- "maximalLengthOfStay": 0
}
}
]
}
]
}Used to create, update, and cancel reservations.
+The exact behavior depends on the agreed communication scheme between Termino and your system.
+status: optionstatus: confirmedThis approach allows gradual state transitions and is the recommended mode for most partners.
+++⚠️ Important: Both
+optionandconfirmedstatuses are expected to block the room in your system.
option request already contains full customer data and voucher code.confirmed request may still be sent but does not need to be processed or relayed to the hotel.You should confirm the preferred mode during your integration setup.
+option request is processed successfullyoption and then confirmed when creating a new reservation (see above)canceled status to cancel the reservationGrouped reservations are currently not implemented; one request always contains only one reservation. Reservation group ID is the same as reservation ID. Reservation response should contain the same data as the request.
+| accessToken required | string Access token to your API. + |
required | string or integer Your hotel id. + |
required | object (ReservationGroup) |
{- "accessToken": "11-11-11-11",
- "hotelId": 123456,
- "reservationGroup": {
- "id": 123456,
- "description": "New Year's Eve 2019",
- "totalPrice": {
- "amount": 1000,
- "currency": "CZK"
}, - "reservations": [
- {
- "id": 123456,
- "status": "option",
- "roomTypeId": 123,
- "term": {
- "start": "2019-01-01",
- "end": "2019-01-02"
}, - "price": {
- "amount": 1000,
- "currency": "CZK"
}, - "adultsCount": 2,
- "children": [
- {
- "age": 5,
- "bedEntitlement": true
}
], - "guestNote": "I would like to have a room with a view.",
- "voucher": "1234567890",
- "contact": {
- "name": "John Doe",
- "phone": "+420123456789"
}
}
]
}
}{- "hotelId": "string",
- "accessToken": "string",
- "reservationGroup": {
- "id": "string",
- "description": "string",
- "reservations": [
- {
- "id": "string",
- "status": "option",
- "roomTypeId": "string",
- "ratePlanId": "string",
- "roomId": "string",
- "term": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "price": {
- "amount": "string",
- "currency": "string"
}, - "meal": "none",
- "adultsCount": 0,
- "childrenCount": 0,
- "children": [
- {
- "age": 0,
- "bedEntitlement": true
}
], - "guestNote": "string",
- "voucher": "string",
- "contact": {
- "name": "string",
- "phone": "string",
- "email": "string"
}
}
], - "totalPrice": {
- "amount": "string",
- "currency": "string"
}
}
}Request for current state of the reservation
+Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
required | string or integer Reservation id. + |
{- "accessToken": "string",
- "hotelId": "string",
- "reservationId": "string"
}{- "id": "string",
- "status": "option",
- "roomTypeId": "string",
- "ratePlanId": "string",
- "roomId": "string",
- "term": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "price": {
- "amount": "string",
- "currency": "string"
}, - "meal": "none",
- "adultsCount": 0,
- "childrenCount": 0,
- "children": [
- {
- "age": 0,
- "bedEntitlement": true
}
], - "guestNote": "string",
- "voucher": "string",
- "contact": {
- "name": "string",
- "phone": "string",
- "email": "string"
}
}Synchronization of changes in reservations created by Termino/Slevomat. This allows changes in reservation made in PMS to be propagated to Termino and Slevomat. Changes can also be pushed via /occupations-update endpoint. +Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Your hotel id. + |
required | object (DateInterval) DateInterval is [start, end) – end date is exclusive. + |
Array of strings or integers Filter occupations on given room types. + |
{- "accessToken": "string",
- "hotelId": "string",
- "interval": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}, - "roomTypeIds": [
- "string"
]
}{- "occupations": [
- {
- "id": "string",
- "type": "reservation",
- "status": "string",
- "roomId": "string",
- "roomTypeId": "string",
- "created": "2019-08-24T14:15:22Z",
- "term": {
- "start": "2019-08-24",
- "end": "2019-08-24"
}
}
]
}Ping endpoint is used to check if hotel exists and synchronization is active on your side.
+If you implement /hotel endpoint, you can ignore this endpoint.
+Usage:
+| accessToken required | string Access token to your API. + |
required | string or integer Hotel id. + |
{- "accessToken": "string",
- "hotelId": "string"
}{- "success": true
}