---
title: "Glofox room bookings — room preparation"
description: "Glofox room bookings over the cloud API, one module per room: Booked now, Minutes to next booking, Prepare room to heat and light it before each booking."
url: "https://taphome.com/en/compatibility/glofox-room-bookings-http/"
language: en
lastmod: 2026-11-10
generator: hugo
ai:
  topics: ["http","cloud-api","rest-api","sensor","room-booking","facility-booking","scheduling","occupancy","fitness-studio"]
  questions: ["How to integrate Glofox room bookings with TapHome?","What does the Glofox room bookings TapHome template read?","How to request Glofox API access for TapHome in the ABC Fitness Developer Portal?","How to find the Glofox Branch ID and the studio time zone?","How to make a room a bookable facility in Glofox?","How to find the Facility ID of a Glofox room?","How to heat a room and switch on lights before a Glofox booking?","Why are the Glofox room values one hour off in TapHome?"]
---

# Glofox room bookings — room preparation

Communication: Packet Parser → HTTP

## Integration guide

Glofox is a cloud booking platform of ABC Fitness, so there is nothing to wire: the TapHome Core reads the room bookings from the Glofox REST API over HTTPS. Setup on the studio side has three parts — Glofox API access for the studio, every rented room set up as a bookable facility, and the studio's Branch ID and time zone. The template is then imported once per room.

Screenshots are from a Glofox Sandbox test location (ABC Fitness Developer Portal and Glofox dashboard, October 2026) and from the TapHome app connected to a test control unit with simulated bookings.

## Configuration

### 1. Request Glofox API access

The studio's **superadmin** signs up in the [ABC Fitness Developer Portal](https://api-portal.glofox.com/api-portal/#/glofox/request-access) (Account Type *Customer*) and clicks **Request Integrator**:

- **Environment:** *Live* (*Sandbox* is only a test location with demo data).
- **Namespace:** the studio's Glofox namespace.
- **Intended Use Case:** for example "TapHome building automation reads facility bookings to prepare rooms (heating, lights, audio) before each booking. Read-only."

ABC Fitness reviews Live requests and answers by e-mail. The **API key** and **API token** are then requested with **Request credentials** and arrive at the portal e-mail address. Questions about access: glofox.apisupport@abcfitness.com.

![Request access guide in the ABC Fitness Developer Portal](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-request-access_hu_ad9d259835295a2f.jpg)

> [!WARNING]
> The API key and the API token give access to the studio's Glofox data. Glofox asks to use them only in backend integrations, never in client-side applications; in TapHome they belong only in the template's import parameters.

### 2. Make every room a bookable facility

First switch on **Settings → Booking → Facility Rental**; the facility switches below appear only after that. Then **Manage → Facilities** lists the rooms. Each room the trainers rent must be a facility with **Bookable** switched on, a slot schedule (*Schedule* tab) and, under *Price / Eligibility*, *Drop In Clients* or *Clients* allowed (a price of 0 is fine). Without them a trainer's booking ends with "Membership not allowed".

![Facilities in the Glofox dashboard](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-facilities_hu_1f8fd4b2268aac05.jpg)

![Facility detail with Public and Bookable switched on](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-facility-bookable_hu_e15ed6a0933935cc.jpg)

### 3. Find the Branch ID and the studio time zone

With the API key and token, one request returns the studio location, its ID and its time zone:

```bash
curl -s -X POST https://gf-api.aws.glofox.com/prod/v3.0/locations/retrieve \
  -H "x-api-key: <API key>" -H "x-glofox-api-token: <API token>" \
  -H "Content-Type: application/json" -d '{}'
```

`data[]._id` is the **BranchId**, `data[].address.timezone_id` the studio time zone (for example `Europe/Bratislava`). Without a filter the request returns every location in the namespaces the integration may read, so with several studios pick the entry of the studio whose rooms the modules watch.

The script clock of the TapHome Core must be in the studio time zone: on Core 2025.2 it is the control unit's system time zone, on newer Core the time zone of the TapHome location.

### 4. Import the template once per room

In the TapHome app open the **Packet Parser** interface (add it first if the control unit has none), then **Add from template → Add from file** and pick the downloaded template. Fill in `ApiKey`, `ApiToken`, `BranchId`, `LeadMinutes` and the room's `FacilityId`.

Put the room name into **Device name prefix** and end it with a separator, for example `Yoga room - `. The prefix is joined to the device names exactly as typed, so without the separator a device is called "Yoga roomBooked now". **Zone** puts the room's three devices into the room's zone.

![Import parameters in the TapHome app](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-app-import_hu_5455f063da370ee.jpg)

If the Facility ID is not known yet, enter any text. After the first poll the module reports an error that lists every facility of the branch with its ID (**Devices → Errors and warnings** → the module):

![Module error listing the facilities of the branch](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-app-error_hu_e4c5cc3bd4339a45.jpg)

Copy the right ID into the module's `FacilityId` variable (or import again) and repeat for every room.

### 5. Check against the Glofox calendar

Bookings of a room appear in the Glofox **Calendar** (filter *Facilities*). With a booking from 10:00 to 11:00 and `LeadMinutes` 60, the room's values are:

| Time | Booked now | Minutes to next booking | Prepare room |
|---|---|---|---|
| 8:30 | Free | 90 | Idle |
| 9:00 | Free | 60 | Prepare |
| 10:30 | Booked | next booking or 1440 | Prepare |
| 11:00 | Free | next booking or 1440 | Idle |

Minutes are whole minutes counted from the poll, so a value can differ from the table by one.

![Facility booking in the Glofox calendar](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-calendar_hu_3b3e02e5fd126f55.jpg)

In the TapHome app each room shows the three values under its module:

![Room values in the TapHome app](https://taphome.com/images/compatibility/glofox-room-bookings-http/glofox-app-devices_hu_e3c9e82eae9fa28e.jpg)

## Smart rules

**Prepare room** is the condition of the room's smart rules: heating or cooling setpoint, lights and audio scene while it is *Prepare*, everything off when it returns to *Idle*. **Booked now** suits occupancy displays; **Minutes to next booking** lets a rule start a slow heating system earlier than `LeadMinutes`.

## Available devices 3

These devices appear in TapHome after import.

Glofox Room Module

Read (module)

```taphome
# Bookings of this room (FacilityId) that run now or start within 24 h. Glofox times are the studio's local time
# ("yyyy-MM-dd HH:mm:ss"), so the Core's time zone must be the studio's. Texts in that format sort like the times,
# which lets JSONPath filters compare them directly.
VAR now := NOW();
VAR nowText := TOSTRING(now, "yyyy-MM-dd HH:mm:ss");
VAR leadText := TOSTRING(DATETIMEADD(now, 0, 0, 0, 0, LeadMinutes), "yyyy-MM-dd HH:mm:ss");
VAR nowLocal := ROUND(now.UNIXTIME + LOCALTIMEZONE() / 1000);
VAR hKey := "x-api-key: " + ApiKey;
VAR hToken := "x-glofox-api-token: " + ApiToken;
VAR hBranch := "x-glofox-branch-id: " + BranchId;
VAR msg := "";
VAR i := 0;
VAR fid := "";

# Every failed poll ends in RETURN before the values are written. After five failed polls in a row (Glofox or the
# internet down) the room is released, so an old "Prepare" does not keep heating and lights on.
failCount := failCount + 1;
IF failCount > 5
    bookedNow := 0;
    prepareRoom := 0;
    minsToNext := 1440;
END

# After start and then once an hour: the configured room must exist; if not, the error lists the rooms of the branch
# with their ids. facilityCheck counts the polls until the next check.
IF facilityCheck <= 0
    VAR fresp := SENDHTTPREQUEST("/prod/3.0/locations/" + BranchId + "/facilities?limit=100", "GET", "", hKey, hToken, hBranch);
    IF !fresp.IsSuccess
        # no connection: StatusCode 0 and no ReasonPhrase
        IF !ISNULL(fresp.ReasonPhrase)
            msg := " " + fresp.ReasonPhrase;
        END
        ADDERROR(1, "Glofox API: HTTP " + TOSTRING(fresp.StatusCode, "F0") + msg);
        RETURN(0);
    END
    IF ISNULL(PARSEJSON(fresp.Content, "$.data", TRUE))
        msg := PARSEJSON(fresp.Content, "$.message", TRUE);
        ADDERROR(2, "Glofox API: " + IF(ISNULL(msg), "unexpected answer", msg));
        RETURN(0);
    END
    IF ISNULL(PARSEJSON(fresp.Content, "$.data[?(@._id == '" + FacilityId + "')].name", TRUE))
        msg := "";
        fid := PARSEJSON(fresp.Content, "$.data[0]._id", TRUE);
        WHILE !ISNULL(fid)
            msg := msg + IF(i = 0, ": ", "; ") + PARSEJSON(fresp.Content, "$.data[" + TOSTRING(i, "F0") + "].name", TRUE) + " = " + fid;
            i := i + 1;
            fid := PARSEJSON(fresp.Content, "$.data[" + TOSTRING(i, "F0") + "]._id", TRUE);
        LOOP
        ADDERROR(3, "Facility '" + FacilityId + "' is not in this branch. Facilities" + msg);
        RETURN(0);
    END
    facilityCheck := 60;
END
facilityCheck := facilityCheck - 1;

VAR path := "/prod/2.2/branches/" + BranchId + "/bookings?status=BOOKED&limit=50&time_finish_start_date=" + TOSTRING(nowLocal, "F0") + "&time_start_end_date=" + TOSTRING(nowLocal + 86400, "F0") + "&page=";
VAR room := "$.data[?(@.model_id == '" + FacilityId + "' && @.status == 'BOOKED' && ";
VAR newBooked := 0;
VAR newPrepare := 0;
VAR nextText := "";
VAR candidate := "";
VAR total := 0;
VAR page := 1;
VAR pages := 1;
VAR nextStart := now;

# limit=50: a booking is about 1 kB (0.9 kB measured) and SENDHTTPREQUEST accepts at most 128 kB; at most 10 pages =
# 500 bookings of the whole branch (class bookings included)
VAR resp := SENDHTTPREQUEST(path + "1", "GET", "", hKey, hToken, hBranch);
WHILE page <= pages
    IF page > 1
        resp := SENDHTTPREQUEST(path + TOSTRING(page, "F0"), "GET", "", hKey, hToken, hBranch);
    END
    IF !resp.IsSuccess
        IF !ISNULL(resp.ReasonPhrase)
            msg := " " + resp.ReasonPhrase;
        END
        ADDERROR(1, "Glofox API: HTTP " + TOSTRING(resp.StatusCode, "F0") + msg);
        RETURN(0);
    END
    # a wrong API token or BranchId answers HTTP 200 with success:false and a message, and no meta
    total := PARSEJSON(resp.Content, "$.meta.totalCount", TRUE);
    IF ISNULL(total)
        msg := PARSEJSON(resp.Content, "$.message", TRUE);
        ADDERROR(2, "Glofox API: " + IF(ISNULL(msg), "unexpected answer", msg));
        RETURN(0);
    END
    pages := MIN(10, CEIL(total / 50));
    IF !ISNULL(PARSEJSON(resp.Content, room + "@.time_start <= '" + nowText + "' && @.time_finish > '" + nowText + "')]._id", TRUE))
        newBooked := 1;
    END
    IF !ISNULL(PARSEJSON(resp.Content, room + "@.time_start <= '" + leadText + "' && @.time_finish > '" + nowText + "')]._id", TRUE))
        newPrepare := 1;
    END
    # earliest booking that has not started: take any later than now, then ask for an earlier one until none is left
    candidate := PARSEJSON(resp.Content, room + "@.time_start > '" + nowText + "'" + IF(nextText = "", "", " && @.time_start < '" + nextText + "'") + ")].time_start", TRUE);
    WHILE !ISNULL(candidate)
        nextText := candidate;
        candidate := PARSEJSON(resp.Content, room + "@.time_start > '" + nowText + "' && @.time_start < '" + nextText + "')].time_start", TRUE);
    LOOP
    page := page + 1;
LOOP
IF total > 500
    ADDWARNING(4, "More than 500 bookings of the branch in the next 24 hours; only the first 500 were read, a booking of this room beyond them is not seen");
END

failCount := 0;
bookedNow := newBooked;
prepareRoom := newPrepare;
IF nextText = ""
    minsToNext := 1440;
ELSE
    nextStart := DATETIME(nextText, "yyyy-MM-dd HH:mm:ss");
    minsToNext := MIN(1440, FLOOR((nextStart.TICKS - now.TICKS) / 60000));
END
```

Booked now Reed Contact

Read

```taphome
RETURN(bookedNow);
```

Minutes to next booking Variable

Read

```taphome
RETURN(minsToNext);
```

Prepare room Reed Contact

Read

```taphome
RETURN(prepareRoom);
```

**Connection:** Packet Parser → HTTP

## Import parameters

Enter these values when you import the XML.

| Asked in the app                                                                 | Default         |
|----------------------------------------------------------------------------------|-----------------|
| Glofox API key (x-api-key header)                                                | Enter at import |
| Glofox API token (x-glofox-api-token header)                                     | Enter at import |
| Glofox Branch ID (x-glofox-branch-id header)                                     | Enter at import |
| Glofox Facility ID for this room (model\_id in booking response)                 | Enter at import |
| Lead time in minutes — Prepare Room activates this many minutes before a booking | `60`            |

## Related Documentation

- [Packet Parser Integration](https://taphome.com/en/compatibility/packet-parser-guide/)
- [Packet Parser (HTTP, TCP, UDP, FTP, MQTT)](https://taphome.com/en/docs/integration/packet-parser/)
- [Packet parser functions](https://taphome.com/en/docs/script/packet-parser/)
- [Parsing functions](https://taphome.com/en/docs/script/parsing-functions/)

