The Hotel API is a two-way bridge between an APRO point-of-sale and any Property Management System (PMS). The PMS pushes reservations into the POS so that guests can charge to their room; the POS exposes those charges back to the PMS so they land on the final hotel invoice.
- Host:
cloudgateway.apro.at(path prefix/hotelservice/) - Auth: API key in
x-api-key - Content type:
application/json - Upstream reference: api-docs.apro.at → hotelservice ↗
Typical flow
PMS APRO POS
│ 1. POST /pms/reservations ─────────▶ │ (upsert guest rooms)
│ │
│ │ guests charge to room…
│ │
│ 2. GET /pms/charges?hotelId=… ─────▶│
│ ◀─── charges (and optionally receipts) │
│ │
│ 3. POST /pms/confirm-charges ───────▶│ (ack; won't be resent)
│ │
│ 4. DELETE /pms/reservations?… ───────▶│ (on check-out / close-out)Step 2 is the PMS's polling loop. Steps 1 and 4 are driven by events in the PMS. Step 3 must always follow a successful poll — otherwise the same charges will be returned again on the next poll.
1. Upsert reservations
Push the current list of active reservations into the POS. Keys are hotelId + Id + guestId; existing rows are updated in place.
POST https://cloudgateway.apro.at/hotelservice/api/v1/pms/reservationsRequest body
Field | Type | Required | Description |
|---|---|---|---|
| Reservation[] | ✅ | One or more reservations. |
Reservation
Field | Type | Required | Description |
|---|---|---|---|
| string | ✅ | PMS-side reservation ID. |
| string | ✅ | PMS tenant / property ID. |
| string | ✅ | PMS-side guest ID. |
| string | ✅ | Assigned room number. |
| string | — |
|
| string | — | |
| string | — | |
| ISO 8601 | ✅ | Check-in timestamp. |
| ISO 8601 | ✅ | Check-out timestamp. |
| integer | — | Guest count, used for covers / buffet rules. |
| Identifier[] | — | Keycard UIDs, NFC tags, room tablets etc. — any token the POS may receive when a guest wants to charge to a room. |
Identifier
Field | Type | Description |
|---|---|---|
| string | The identifier value (keycard UID, token). |
Example request
POST /hotelservice/api/v1/pms/reservations
{
"reservations": [
{
"Id": "Aabc123",
"hotelId": "1",
"guestId": "Abc123",
"roomNr": "Abc123",
"title": "Mr.",
"firstName": "Max",
"lastName": "Mustermann",
"arrival": "2026-04-02T14:00:00",
"departure": "2026-04-04T14:00:00",
"nrOfIndividuals": 1,
"identifiers": [{ "value": "keycard-uid" }]
}
]
}Download: hotel-reservations-upsert.json
Example response
200 OK
{
"newReservationsCount": 0,
"checkedOutReservationsCount": 0,
"updatedReservationsCount": 1,
"state": 1,
"isSuccessfull": true,
"errorCode": 0,
"message": null,
"context": null
}Download: hotel-reservations-response.json
Tip
Push the full active reservation set on every call, not deltas.checkedOutReservationsCountreflects reservations the POS was tracking
but which are no longer in your payload — it removes them automatically.
2. Poll charges
Fetch everything booked against rooms since the last confirmed poll.
GET https://cloudgateway.apro.at/hotelservice/api/v1/pms/charges
?hotelId=1
&excludeAlreadyExported=trueQuery parameters
Name | Type | Required | Description |
|---|---|---|---|
| string | ✅ | PMS tenant / property ID. |
| bool | — |
|
Response shape
Each item has a chargeType that controls which fields are populated:
| Meaning |
|
|---|---|---|
| An open line booked to the room (guest hasn't paid yet — POS is posting to the room folio). | no |
| A closed receipt (guest settled at the POS; PMS may ignore or reconcile). | yes |
Top-level envelope:
Field | Type | Description |
|---|---|---|
| integer | Page size applied. |
| integer | Offset into the backlog. |
| integer | Items still unconfirmed in total. |
| Item[] | Charges and receipts. |
Item
Field | Type | Description |
|---|
| `"Charge" | "Receipt"` | See table above. |
| ISO 8601 | When the line was booked in the POS. |
| integer | POS receipt number. |
| integer | Operator / waiter ID. |
| string | Operator name. |
| integer | Outlet ID (e.g. |
| integer | Table number. |
| string | Table label. |
| decimal | Gross total of the line. |
| decimal | Included tip. |
| GUID | APRO transaction ID — use this as the |
| string | null | PMS reservation ID, for |
| string | null | PMS guest ID. |
| string | null | Room number. |
| LineItem[] | Individual article rows. |
| Payment[] | Only on |
LineItem
Field | Type | Description |
|---|---|---|
| integer | Product number. |
| string | Product name. |
| integer | Category (Sparte) number. |
| string | Category name. |
| decimal | Quantity. |
| decimal | Gross unit price. |
| decimal | Applied VAT rate. |
Example response
200 OK · charge + two receipts
{
"page": { "limit": 3, "offset": 0, "total": 8096 },
"data": [
{
"chargeType": "Charge",
"bookDate": "2026-04-15T09:15:04.95",
"receiptNr": 90,
"userId": 20,
"userName": "Johannes",
"outlet": 1,
"tableNr": 2,
"table": "Bar 2",
"totalAmount": 9.00,
"tip": 0.30,
"businesscaseId": "253c225f-7c4a-4d3f-80cd-63de4dbfca9e",
"reservationId": " 15631",
"guestId": " 6158",
"roomNumber": " 414",
"charges": [
{ "articleNr": 129, "articleName": "Zipfer 0,2", "productgroupName": "Bier", "quantity": 1.00, "unitPrice": 1.10, "vatPercent": 20.00 },
{ "articleNr": 213, "articleName": "Apfel ltg 0,5", "productgroupName": "Flaschen AF", "quantity": 1.00, "unitPrice": 2.70, "vatPercent": 20.00 },
{ "articleNr": 1626, "articleName": "Würstel Pommes", "productgroupName": "Hauptspeise", "quantity": 1.00, "unitPrice": 4.90, "vatPercent": 10.00 }
]
}
]
}Download the full sample (Charge + two Receipts): hotel-charges-response.json
Caution
String fields likereservationId,guestId,roomNumbermay be left-
padded with spaces when the POS stores them as fixed-width columns
(" 15631"). Trim on the PMS side before matching.
3. Confirm charges
Acknowledge the list you've successfully ingested. Once confirmed, the POS won't return those businesscaseIds on a subsequent poll with excludeAlreadyExported=true.
POST https://cloudgateway.apro.at/hotelservice/api/v1/pms/confirm-chargesRequest body
Field | Type | Required | Description |
|---|---|---|---|
| string | ✅ | PMS tenant / property ID. |
| GUID[] | ✅ |
|
POST /hotelservice/api/v1/pms/confirm-charges
{
"hotelId": "1",
"transactionIds": [
"69F94B1A-3453-7017-8DDB-94E2175D0365",
"155FFA87-DC19-EB1F-3DD8-540EF62A115D"
]
}Download: hotel-confirm-charges.json
4. Remove a reservation
Explicit removal — useful at check-out or when the guest should no longer be able to charge to the room.
DELETE https://cloudgateway.apro.at/hotelservice/api/v1/pms/reservations
?hotelId=1
&reservationId=Abc123
&guestId=Abc123All three query parameters are required. Either the targeted reservation is removed, or the call is a no-op if it doesn't exist.
Note
In practice the full-set upsert on step 1 is enough — any reservation
no longer present in the payload is checked out automatically
(checkedOutReservationsCount). Use this endpoint only when you need
an explicit out-of-band removal.
Idempotency & retries
POST /pms/reservationsis idempotent on{ hotelId, Id, guestId }. Re-sending the same payload converges to the same state.POST /pms/confirm-chargesis idempotent ontransactionIds. Re-confirming an already-confirmed ID is a no-op.- Poll → confirm must be transactional in your own system: write the charges to your ledger first, then confirm. If the confirm fails, the same rows are returned next poll.
Errors
See Authentication → Error responses. On business-logic failures the response shape is:
{
"isSuccessfull": false,
"errorCode": 42,
"message": "No reservation found for guestId 'Abc123'.",
"context": { "guestId": "Abc123" }
}