What this is
A studio that uses Hive can let another system read its calendar. That's what you need, for example, to send a member a reminder of their appointment from an outside service.
Everything is read-only. There's no way to book, move, cancel or confirm an appointment from here. And no health data about the member is sent: what's left out.
The studio decides whether to open its calendar, and can close it whenever it wants. If you stop getting responses, the first thing to ask them is whether they revoked the key.
How to get the key
The studio generates it, not us. An administrator goes to Settings → Integrations, creates a key for "an external service" and copies it with a button.
It's best to use one key per provider: that way the studio can cut one off without leaving the others without service. And treat it like a password — whoever has it can see that calendar.
Querying appointments
curl -H "Authorization: Bearer YOUR_KEY" \
"https://hivegyms.com/api/v1/appointments?desde=2026-08-26&hasta=2026-09-02"
Without the header, or with an invalid or revoked key, it responds 401.
Parameters
| Parameter | What it does |
|---|---|
| desde hasta |
Date range (YYYY-MM-DD). Maximum 62 days
per query. Without them: today and the next seven days.
For a single day, use the same date in both.
|
| sucursal_id |
Only that branch's appointments. The IDs are listed in the response's sucursales.
|
| actualizadas_desde | ISO 8601 timestamp. Returns only what changed since then — the cheap way to ask "what changed?" instead of sweeping the whole calendar every time. |
| cursor | Next page. It comes in siguiente_cursor. |
| limite | Appointments per page. Maximum 500, default 200. |
The response
{
"ok": true,
"desde": "2026-08-26",
"hasta": "2026-09-02",
"zona": "America/Bogota",
"sucursales": [
{ "id": 3, "nombre": "Sede Norte" },
{ "id": 4, "nombre": "Sede Sur" }
],
"siguiente_cursor": null,
"citas": [
{
"id": 4821,
"fecha": "2026-08-27",
"hora": "10:00",
"duracion_minutos": 30,
"inicio": "2026-08-27T10:00:00-05:00",
"zona": "America/Bogota",
"estado": "confirmada",
"recordatorio": "ninguno",
"sucursal": { "id": 3, "nombre": "Sede Norte" },
"coach": { "id": 12, "nombre": "Coach Forero" },
"socio": {
"id": 990,
"nombre": "Juan Pérez",
"telefono": "+57 3001112233",
"email": "[email protected]",
"acepta_whatsapp": true
},
"actualizada_en": "2026-08-26T09:12:44Z"
}
]
}
The time: use inicio
This is the easiest mistake to make here.
fecha and hora are the studio's wall-clock
time: "10:00" means ten o'clock at the studio, with no time zone.
inicio is that same moment with the branch's real offset, and it's the only field
you should calculate "24 hours before" against. If you subtract from the bare time, reminders go
out at the wrong time.
That's why zona comes per appointment and not per studio: a chain
can have branches in different time zones, and Tijuana and Mexico City are two hours apart.
Studios with multiple branches
Every response includes sucursales with the branches that key
can reach, and each appointment says which one it belongs to. There are two ways to work, depending on how the
studio created it:
One key for the whole studio
The usual case. Appointments from all branches come together, each with its sucursal.
If you only care about one, filter with sucursal_id.
One key per branch
The studio restricts it when creating it, and that key can't see the others no matter how you ask.
Asking for a sucursal_id the key can't reach responds
422 with the reason, not an
empty list — so "there are no appointments" isn't confused with "I don't have access".
Fields that may be empty
coach is null for appointments booked without an assigned professional (it happens at
the front desk, it's normal). telefono and email are null when the
studio doesn't have them on file.
It's worth counting them before promising coverage: the number of appointments isn't the number of reminders that can be sent.
acepta_whatsapp
Says whether someone explicitly marked on the member profile that they accept WhatsApp messages.
It's informational, not an instruction. Today most have it set to
false simply because nobody has gone and marked it, not because they refused: the
real consent is held by the studio in its privacy notice, signed when the record was opened.
The studio decides who gets messaged, and it's an agreement between the studio and its provider. If the rule is "only those who opted in", this field is useful for filtering; if it's "everyone who left a phone number" —which is what Hive's own WhatsApp does— the field is ignored.
Appointment statuses
programada · confirmada · llego · en_silla · en_procedimiento · checkout · completada · cancelada · no_asistio · reagendar
Cancelled ones do appear: knowing an appointment fell through is often half the reason to query. What never appears are schedule blocks (lunches, meetings) or appointments deleted by mistake.
recordatorio is the status of the reminder Hive sends
over WhatsApp (ninguno, enviado, entregado, fallido).
If a third party sends the reminders, that field stays at ninguno.
Limits and errors
60 requests per minute per key.
| Code | When |
|---|---|
| 401 | Missing, invalid or revoked key. |
| 422 | Malformed dates, a range longer than 62 days, or a branch the key can't reach. |
| 429 | More than 60 requests in a minute. |
All of them respond { "ok": false, "error": "…" } with the reason as text.
Calendar feed
To see the calendar in Google Calendar, on an iPhone or in Outlook you don't need to code anything: in Settings → Integrations the studio generates an address that you paste into the calendar as "subscribe by URL".
Google Calendar decides on its own how often to check again, and it usually takes between 8 and 24 hours. There's no way to speed it up. It's good for seeing the week; to react to a last-minute change you need to use the API.
It covers from 30 days back to 180 days ahead, without cancelled appointments (so the slot clears from the calendar by itself), and each event carries only the member's name, the coach and the branch.
What it does NOT return, and it's not an oversight
No progress notes, no reason for the visit written on the appointment, no services, plans, quotes, balances, allergies or health history. That's health data, the studio answers for it, and none of it is needed to remind a member of their appointment.
There's also no way to write: no booking, moving, cancelling or confirming. If a workflow needs it, let's talk — it's left out on purpose, not for lack of time.