Introduction

Welcome to the 12RND & UBX Performance Hub API. This API Manages club data & key systems that integrate with your club and it's external systems systems, and is not publicly consumable API. For further information about using the various Performance Hub systems this API supports, please refer to our [Internal Wiki](https://portal.hub.gymsystems.co/wiki)'s individual entry for the system you require.

Base URL

https://portal.hub.gymsystems.co

Alternative Environments

https://portal.hub.gymsystems.co - Performance Hub API - Production
https://portal.hub.stage.gymsystems.co/ - Performance Hub API - Staging

Authentication

Authentication details will be provided when your integration is approved.

Device-reported "agent turn complete" event (web push trigger)

Called by a paired AI Agent device's sidecar (never by browsers) when a web-UI-initiated agent run finishes and ran longer than the device's notify threshold. Authenticated with a short-lived per-device HS256 JWT (aud 'events'). Deduped per device+session+start and rate-limited per device, then delivered to the initiating user's HTML5 push subscriptions with a deep link to the conversation.

Request Body

Endpoint

POST /ai/events/agent-turn-complete

Example Request

curl -X POST https://portal.hub.gymsystems.co/ai/events/agent-turn-complete \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Agent-initiated push notification (ph-notify skill)

Called by a paired AI Agent device's sidecar on behalf of the on-device agent (the ph-notify skill) to push an arbitrary notification to a user's browser and mobile devices. Authenticated with a short-lived per-device HS256 JWT (aud 'events'). The target user must have access to the device (per-agent access policy); when omitted, the notification goes to the device owner. Rate-limited per device, separately from turn-complete events.

Request Body

Endpoint

POST /ai/events/agent-notify

Example Request

curl -X POST https://portal.hub.gymsystems.co/ai/events/agent-notify \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Upload a notification image (ph-notify skill)

Accepts a raw image body from a paired device (aud 'events' JWT) and stores it in the public notify-media bucket under an unguessable UUID key. Objects auto-delete after 7 days (S3 lifecycle). Returns the public https URL for use as `imageUrl` in /ai/events/agent-notify. 5 MB cap; png/jpeg/gif/webp only.

Request Body

Endpoint

POST /ai/media/notify-image

Example Request

curl -X POST https://portal.hub.gymsystems.co/ai/media/notify-image \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List AI Agent relays (platform admin)

Returns all relay registry rows including PH-only fields and health.

Endpoint

GET /api/devices/ph-ai-agent/relays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/relays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Seed the AI Agent relay registry for this stage (platform admin)

Endpoint

POST /api/devices/ph-ai-agent/relays/seed

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/relays/seed \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert an AI Agent relay row (platform admin)

Parameters

region `string` (required)

Endpoint

PUT /api/devices/ph-ai-agent/relays/{region}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/relays/{region} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete an AI Agent relay row (platform admin)

Parameters

region `string` (required)

Endpoint

DELETE /api/devices/ph-ai-agent/relays/{region}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/relays/{region} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Device MCP relay for Connected Apps (external SaaS tools)

Streamable-HTTP MCP endpoint for paired AI Agent devices ("connected_apps" MCP server on the device sidecar's :8790 listener). Authenticated with a short-lived per-device HS256 JWT (aud 'mcp' — same credential as /mcp) and gated on the AGENT's Connected Apps enabled flag (connections are per agent device, not per facility). Requests stream through to the agent's own upstream tool-platform session MCP server with the session headers injected server-side; upstream credentials never reach the device. Tool names and vendor branding are white-labeled bidirectionally in transit. An upstream 401/410 (expired session) triggers one session recreation + retry.

Endpoint

POST /mcp/apps

Example Request

curl -X POST https://portal.hub.gymsystems.co/mcp/apps \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all agreements in the system

Endpoint

GET /api/admin/agreements/list-agreements

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/agreements/list-agreements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Uploads an agreement into the system.

Parameters

body `string` (required) Json object containing the agreement and parameters to add/upload to the system ...

Endpoint

PUT /api/admin/agreements/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/agreements/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Uploads an agreement into the system.

Parameters

file `string` (optional) File attachment of agreement (pdf/doc)

Endpoint

POST /api/admin/agreements/upload-attachment

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/agreements/upload-attachment \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists the number of agreements that are outstanding and require action based on a user and what clubs is associated with it

Endpoint

GET /api/agreements/agreements-outstanding

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agreements/agreements-outstanding \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all agreements available to a club

Parameters

club `string` (required) Internal ID of the club that you wish to access. contracts-sort `string` (optional) Sort agreements by date-effective or alphabetical. Defaults to date-effective. contracts-acknowledgement `string` (optional) Filter agreements by all, acknowledged or unacknowledged. Defaults to all. contracts-requirement `string` (optional) Filter agreements by all, signature, checkbox, popup or none. Defaults to all. contracts-status `string` (optional) Filter agreements by all, active or archived. Defaults to all.

Endpoint

GET /api/agreements/list-agreements/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agreements/list-agreements/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Signs an agreement based on it's ID.

Parameters

club `string` (required) Internal ID of the club that is signing the agreement. agreementid `string` (required) ID of the agreement that is being signed. body `string` (required) Json object containing the agreement and parameters to add/upload to the system ...

Endpoint

POST /api/agreements/sign/{club}/{agreementid}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agreements/sign/{club}/{agreementid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Debug Redis keys for audit logs (super-admin only)

Lists all Redis keys related to audit logs for debugging cache structure

Endpoint

GET /api/admin/audit-logs/debug-redis-keys

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/debug-redis-keys \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generate AI summary for audit log error

Uses LLM to generate a human-readable summary of an API error from audit log details

Request Body

Endpoint

POST /api/admin/audit-logs/generate-error-summary

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/audit-logs/generate-error-summary \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Query audit logs by IP address (Global Admin only)

Retrieve all API access logs from a specific IP address

Parameters

ipAddress `string` (required) IP address startTime `number` (optional) Start time (Unix timestamp) endTime `number` (optional) End time (Unix timestamp) limit `number` (optional) Maximum number of results

Endpoint

GET /api/admin/audit-logs/query-by-ip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/query-by-ip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Query audit logs by user email (Global Admin only)

Retrieve all API access logs for a specific user

Parameters

email `string` (required) User email address startTime `number` (optional) Start time (Unix timestamp) endTime `number` (optional) End time (Unix timestamp) limit `number` (optional) Maximum number of results

Endpoint

GET /api/admin/audit-logs/query-by-user

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/query-by-user \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search API audit logs (IAM & Admin module access)

Search and filter API access logs with advanced filtering capabilities. Users can only see logs for organisations they have access to.

Parameters

organisationId `string` (optional) Organisation ID for ACL verification (required for non-super-admin users)

Request Body

Endpoint

POST /api/admin/audit-logs/search

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/audit-logs/search \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get cached audit log statistics from Redis (IAM & Admin module access)

Retrieve aggregated statistics from Redis cache for instant dashboard loading

Parameters

timeWindow `string` (optional) Time window for statistics (defaults to 12h)

Endpoint

GET /api/admin/audit-logs/statistics-cached

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/statistics-cached \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get audit log statistics (IAM & Admin module access)

Retrieve aggregated statistics for the dashboard. Scoped to user's organisations.

Parameters

startTime `number` (optional) Start time (Unix timestamp), defaults to 24 hours ago endTime `number` (optional) End time (Unix timestamp), defaults to now

Endpoint

GET /api/admin/audit-logs/statistics

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/statistics \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get time series data for audit logs (IAM & Admin module access)

Retrieve bucketed time series data for request timeline visualization

Parameters

timeWindow `string` (optional) Time window for time series data: - 1h: Last 1 hour (10-minute blocks) - 12h: Last 12 hours (10-minute blocks) - 24h: Last 24 hours (10-minute blocks) - 7d: Last 7 days (1-hour blocks) - 14d: Last 14 days (1-hour blocks)

Endpoint

GET /api/admin/audit-logs/timeseries

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/timeseries \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get organisations the user has access to for audit logs (IAM & Admin module access)

Returns the list of organisations the current user can view audit logs for

Endpoint

GET /api/admin/audit-logs/user-organisations

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/audit-logs/user-organisations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of clubs that implements the global agreement templates.

Endpoint

GET /api/admin/club-agreement-variation

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/club-agreement-variation \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create user agreement.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

POST /api/admin/club-user-agreements

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/club-user-agreements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of agreement.

Endpoint

GET /api/admin/club-user-agreements

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/club-user-agreements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of default config agreement from table.

Endpoint

GET /api/admin/cua-config-agreements

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/cua-config-agreements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete user agreement.

Endpoint

DELETE /api/admin/club-user-agreements/:id

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/club-user-agreements/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns specific of agreement.

Endpoint

GET /api/admin/club-user-agreements/:id

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/club-user-agreements/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update user agreement.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

PATCH /api/admin/club-user-agreements/:id

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/admin/club-user-agreements/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

The initial call to create a new club... Note only the 'template' club object is created - A second API request is then required to update the club with it's data such as Opening Hours, Location, Social URL's etc.

Parameters

body `string` (required) Json Object of the new club to add to the system.

Endpoint

POST /api/admin/clubs/addclub

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/clubs/addclub \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Move a facility to a different brand/organisation

Updates a facility's brandId to move it to a different brand (and therefore organisation). Super admin only.

Parameters

club `string` (required) The facility ID to move

Request Body

Endpoint

POST /api/admin/clubs/move-facility/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/clubs/move-facility/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Lists all agreements in the system

Endpoint

GET /api/admin/db-sync/list-tables

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/db-sync/list-tables \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Checks for unscheduled sms and schedule them, unless the send date has already passed in which case send the sms immedietly

Parameters

socketID `string` (optional) ID of the websocket (if connected) to return realtime logs to dryRun `string` (required) either a 'true' or 'false' value which specifies if you wish to perform a 'Dry Run' (Just returns a log without modifying data) or actually modify/sync tables. tables `string` (required) Array of tables to sync from prod to stage

Endpoint

POST /api/admin/db-sync/sync-from-prod

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/db-sync/sync-from-prod \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns single email mapping based on id

Endpoint

GET /api/admin/email-mapping/:id

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/email-mapping/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns single faq item based on faqId

Endpoint

GET /api/admin/faqs/:faqId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/faqs/:faqId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all faq items that contains the specific category

Endpoint

GET /api/admin/faqs/category/:category

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/faqs/category/:category \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all hardware devices registered in our system & warranty information (if available)

Endpoint

GET /api/admin/hardware/all-devices

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/hardware/all-devices \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all holidays that are available to country, including global holidays and organisation-specific overrides.

Parameters

countryIso `string` (optional) Country iso. organisationId `string` (optional) Organisation ID. If not provided, returns global holidays only.

Endpoint

GET /api/admin/country/{countryIso}/holidays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/country/{countryIso}/holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a country's blacklisted holidays.

Parameters

countryIso `string` (optional) Country iso. organisationId `string` (required) Organisation ID. If not provided, updates global holidays. body `string` (required)

Endpoint

PUT /api/admin/country/{countryIso}/holidays

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/country/{countryIso}/holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists SMS Bulk history

Parameters

organisationId `string` (required) The organisation ID to filter the SMS history for.

Endpoint

GET /api/admin/sms/message-history

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/sms/message-history \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a new SMS to one or more numbers.

Parameters

body `string` (required) Json Object with post params for new message to send.

Endpoint

POST /api/admin/sms/new-message

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/sms/new-message \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Schedules an sms to be sent.

Parameters

body `string` (required) Json Object of the user data that you wish to add/update.

Endpoint

POST /api/admin/sms/schedule

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/sms/schedule \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds a new user to the system

Parameters

body `string` (required) Json Object of the user data that you wish to add/update.

Endpoint

POST /api/users

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/users \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Check if user is simulated

Returns true if the x-simulated-user header is present in the request

Parameters

x-simulated-user `string` (optional) Header indicating if user is simulated

Endpoint

GET /api/admin/users/is-simulated-user

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/users/is-simulated-user \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all users (Google Apps Accounts) that have access to the backoffice system/api

Endpoint

GET /api/admin/users/listusers

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/users/listusers \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List MCP keys for a user (redacted). Users can list their own keys; global admins can list any user's keys.

Parameters

userId `string` (required)

Endpoint

GET /api/users/{userId}/mcp-keys

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/users/{userId}/mcp-keys \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a new MCP API key for a user. Users can create their own keys; global admins can create keys for any user.

Parameters

userId `string` (required) body `object` (optional)

Endpoint

POST /api/users/{userId}/mcp-keys

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/users/{userId}/mcp-keys \
  -H "x-api-key: YOUR_API_KEY"

Revoke/remove an MCP API key. Users can delete their own keys; global admins can delete any user's keys.

Parameters

userId `string` (required) keyId `string` (required)

Endpoint

DELETE /api/users/{userId}/mcp-keys/{keyId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/users/{userId}/mcp-keys/{keyId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remove a role from a user

Parameters

userId `string` (optional) The email of the user you wish to remove the role from. roleId `string` (optional) The ID of the role you wish to remove from the user.

Endpoint

DELETE /api/users/{userId}/roles/{roleId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/users/{userId}/roles/{roleId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remove a user from performance hub

Parameters

userId `string` (optional) The email of the user you wish to remove the role from. roleId `string` (optional) The ID of the role you wish to remove from the user.

Endpoint

DELETE /api/users/{userId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/users/{userId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates an existing user's profile details (firstName, lastName, phoneNumber)

Parameters

userId `string` (required) User's email address body `object` (required) User profile data to update

Endpoint

PATCH /api/users/{userId}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/users/{userId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search Clubpass users

Endpoint

GET /api/admin/users/searchuser

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/users/searchuser \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Send welcome email to a user

Sends a welcome email with access summary, sign-in instructions, and a link to set up a password. Requires super admin access.

Parameters

userId `string` (required) Email address of the user

Endpoint

POST /api/admin/users/{userId}/send-welcome-email

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/users/{userId}/send-welcome-email \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert a user role

Parameters

body `object` (optional)

Endpoint

PUT /api/users/{userId}/roles

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/users/{userId}/roles \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create config block

Parameters

body `string` (required) Json Object of the new config block to add to the system.

Endpoint

POST /api/admin/charges-config

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/charges-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all config blocks available to admin

Parameters

organisationId `string` (required)

Endpoint

GET /api/admin/charges-config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/charges-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get config block applicable to club

Parameters

club `string` (required) hideInactive `string` (optional) Hide inactive config blocks and only return active ones showDisabledFees `string` (optional) Show all transaction type fees, including failed and chargeback

Endpoint

GET /api/club/{club}/charges-config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/charges-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete an admin note from a facility.

Parameters

facilityId `string` (required) Internal ID of the facility that you wish to access. noteId `string` (required) ID of the admin note to delete.

Endpoint

DELETE /api/facilities/{facilityId}/admin-notes/{noteId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/facilities/{facilityId}/admin-notes/{noteId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all admin notes for a facility.

Parameters

facilityId `string` (required) Internal ID of the facility that you wish to access. body `object` (optional)

Endpoint

GET /api/facilities/{facilityId}/admin-notes

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/admin-notes \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert an admin note to a facility.

Parameters

facilityId `string` (required) Internal ID of the facility that you wish to access. body `object` (optional)

Endpoint

PUT /api/facilities/{facilityId}/admin-notes

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/facilities/{facilityId}/admin-notes \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates club info in expresscart store v2.

Parameters

clubID `string` (required)

Endpoint

PUT /api/admin/store/clubs/{clubID}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/store/clubs/{clubID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a new location entity on yext.

Parameters

facilityId `string` (optional) The facility ID to create the location for.

Endpoint

GET /api/admin/yext/location

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/yext/location \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a location entity on yext.

Parameters

entityId `string` (optional) facilityId `string` (optional) The facility ID to delete the location for.

Endpoint

DELETE /api/admin/yext/location/{entityId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/yext/location/{entityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates an existing location entity on yext.

Parameters

id `string` (required) Location id facilityId `string` (optional) The facility ID to update the location for.

Endpoint

GET /api/admin/yext/location/{id}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/yext/location/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

list all listings given a club.

Parameters

clubId `string` (required)

Endpoint

GET /api/admin/club/{clubId}/yext/listings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/club/{clubId}/yext/listings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create new email mapping record

Parameters

body `string` (required) Json Object of the new email mapping to add to the system.

Endpoint

POST /api/admin/email-mapping/add

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/email-mapping/add \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete email mapping

Parameters

id `string` (required) ID of the email mapping body `string` (required) Json Object of email mapping that you wish to update.

Endpoint

DELETE /api/admin/email-mapping/delete/{id}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/email-mapping/delete/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all email mappings

Endpoint

GET /api/admin/email-mapping

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/email-mapping \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update email mapping

Parameters

id `string` (required) ID of the email mapping body `string` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/email-mapping/update/{id}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/email-mapping/update/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create new faq record

Parameters

body `string` (required) Json Object of the new faq to add to the system.

Endpoint

POST /api/admin/faqs/add

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/faqs/add \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete faq item

Parameters

faqId `string` (required) ID of the faq item body `string` (required) Json Object of club data that you wish to update.

Endpoint

DELETE /api/admin/faqs/delete/{id}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/faqs/delete/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all faq items

Endpoint

GET /api/admin/faqs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/faqs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update faq item

Parameters

faqId `string` (required) ID of the faq item body `string` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/faqs/update/{id}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/faqs/update/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates new landing page

Parameters

body `string` (required) Json Object of the new landing page to add to the system.

Endpoint

POST /api/admin/landing-pages

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/landing-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deletes a landing page

Parameters

body `string` (required) Json Object of the landing page to delete from the system.

Endpoint

DELETE /api/admin/landing-pages

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/landing-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists landing pages

Endpoint

GET /api/admin/landing-pages

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/landing-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a landing page

Parameters

body `string` (optional) Json Object of the landing page to udpate.

Endpoint

PATCH /api/admin/landing-pages

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/admin/landing-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create new press record

Parameters

body `string` (required) Json Object of the new press to add to the system.

Endpoint

POST /api/admin/press/add

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/press/add \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete press item

Parameters

pressId `string` (required) ID of the press item body `string` (required) Json Object of club data that you wish to update.

Endpoint

DELETE /api/admin/press/delete/{id}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/press/delete/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all press items

Endpoint

GET /api/admin/press

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/press \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns single faq item based on pressId

Endpoint

GET /api/admin/press/:pressId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/press/:pressId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update press item

Parameters

pressId `string` (required) ID of the press item body `string` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/press/update/{pressId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/press/update/{pressId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Billing health directory across every organisation and facility: resolved billing profile, payment settings flags (locked/paused), wallet balance for prepaid payers, the last twelve months' record statuses, and outstanding/overdue money rollups. Powers the Billing Administration applet's Directory view and its needs-attention dashboards. Super-admin only.

Parameters

includeArchived `string` (optional) Include archived facilities and their historical spend (default false).

Endpoint

GET /api/admin/saas-billing/directory

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/directory \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Wallet summary + full transaction ledger + top-up invoices for any owner (facility# or org#). Super-admin only — the club-facing wallet API is scoped to the caller's facility, this one is not.

Parameters

ownerKey `string` (required) URL-encoded owner key, e.g. facility%23TestClub or org%23Org1

Endpoint

GET /api/admin/saas-billing/wallets/{ownerKey}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/wallets/{ownerKey} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manual wallet adjustment. Positive amountCents credits the wallet (grant), negative debits it (correction). A note is required — it is the only audit trail on manual money movement. Credits that bring the balance above zero clear depletion markers and immediately re-evaluate lockout for facility wallets. Super-admin only.

Parameters

ownerKey `string` (required) body `string` (optional) { amountCents: integer (non-zero, positive=credit), note: string }

Endpoint

POST /api/admin/saas-billing/wallets/{ownerKey}/adjust

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/wallets/{ownerKey}/adjust \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Cancel a pending top-up invoice (paid invoices cannot be cancelled). Super-admin only.

Parameters

invoiceId `string` (required)

Endpoint

POST /api/admin/saas-billing/topup-invoices/{invoiceId}/cancel

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/topup-invoices/{invoiceId}/cancel \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Consolidated organisation monthly records (org# rows) with full detail — per-facility breakdown, report, settlement and communication logs. The customer-facing org endpoint sanitizes these; this one does not. Super-admin only.

Parameters

organisationId `string` (required)

Endpoint

GET /api/admin/saas-billing/org/{organisationId}/monthly-records

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/org/{organisationId}/monthly-records \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List every billing profile row (org profiles + facility overrides). Super-admin only.

Endpoint

GET /api/admin/saas-billing/billing-profiles

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update a billing profile row. Super-admin only.

Parameters

body `string` (optional) { ownerKey: 'org#'|'facility#', billingMethod?, paymentMethod?, payerScope?, billingDisabled?, netDays?, lockoutPolicy?, autoTopup? }. billingDisabled=true meters usage but never bills the owner and removes it from every financial rollup; set on an org to cover all its facilities, or false on a facility to exempt it.

Endpoint

PUT /api/admin/saas-billing/billing-profiles

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Snapshot outstanding monthly records (and a negative prepaid wallet) before a billing-method flip. Super-admin only. Query `to` is the intended billingMethod after save.

Parameters

ownerKey `string` (optional) 'org#' or 'facility#' (URL-encoded) to `string` (optional) Intended billingMethod after the flip

Endpoint

GET /api/admin/saas-billing/billing-profiles/migration-preflight/{ownerKey}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles/migration-preflight/{ownerKey} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a billing profile row so the owner falls back to inheritance (facility override -> org profile -> platform default). Super-admin only.

Parameters

ownerKey `string` (optional) 'org#' or 'facility#' (URL-encoded)

Endpoint

DELETE /api/admin/saas-billing/billing-profiles/{ownerKey}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles/{ownerKey} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Preview the EFFECTIVE billing profile a facility resolves to (facility override -> org profile -> platform default) with per-field sources for inheritance display. Super-admin only.

Parameters

clubID `string` (optional) Facility ID

Endpoint

GET /api/admin/saas-billing/billing-profiles/resolve/{clubID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles/resolve/{clubID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Preview the effective billing profile at ORGANISATION scope (org profile -> platform default). Super-admin only.

Parameters

organisationId `string` (optional) Organisation ID

Endpoint

GET /api/admin/saas-billing/billing-profiles/resolve-org/{organisationId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/billing-profiles/resolve-org/{organisationId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Model Router admin summary for a facility

Facility row, prepaid ledger, live-effective remaining, auto-recharge, pause flag, and recent money-movement transactions. Super-admin only.

Parameters

clubID `string` (required)

Endpoint

GET /api/admin/saas-billing/model-router/facilities/{clubID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Grant or debit Model Router credits

Positive amountCents grants complimentary credit (no card charge). Negative amountCents claws back unused credit. Note is required. Super-admin only. Cap is $5,000 per operation.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/admin/saas-billing/model-router/facilities/{clubID}/adjust

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/adjust \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Pause or resume Model Router inference

Sets inferencePaused on the facility row. The /ai prepaid gate returns 402 while paused, independent of remaining credits. Super-admin only.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/admin/saas-billing/model-router/facilities/{clubID}/pause

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/pause \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable or disable Model Router auto-recharge

Turns auto-recharge off (nulls threshold and amount so the cron will not charge) or on (requires thresholdCents and amountCents). Super-admin only.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/admin/saas-billing/model-router/facilities/{clubID}/auto-recharge

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/auto-recharge \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Model Router transaction ledger for a facility

Parameters

clubID `string` (required) limit `string` (optional) types `string` (optional) from `string` (optional) to `string` (optional)

Endpoint

GET /api/admin/saas-billing/model-router/facilities/{clubID}/transactions

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/transactions \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Top-up receipt PDF (admin)

Parameters

clubID `string` (required) txId `string` (required)

Endpoint

GET /api/admin/saas-billing/model-router/facilities/{clubID}/transactions/{txId}/receipt.pdf

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/transactions/{txId}/receipt.pdf \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Monthly Model Router usage rollups (admin)

Parameters

clubID `string` (required) months `string` (optional)

Endpoint

GET /api/admin/saas-billing/model-router/facilities/{clubID}/usage-statements

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/usage-statements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Monthly usage statement PDF (admin)

Parameters

clubID `string` (required) month `string` (required)

Endpoint

GET /api/admin/saas-billing/model-router/facilities/{clubID}/usage-statements/{month}/statement.pdf

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/model-router/facilities/{clubID}/usage-statements/{month}/statement.pdf \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Billing and revenue analytics for one organisation: monthly billed vs collected vs outstanding series, AR aging buckets, revenue by facility, revenue by charge category, and headline totals. Powers the Analytics view in the Billing Administration applet. Super-admin only.

Parameters

organisationId `string` (required) months `string` (optional) Lookback window in months (default 12, max 24). clubID `string` (optional) When set, analytics are scoped to this facility (must belong to the organisation). Billed-to-org facility records count in the receivable series here so the facility still sees its contribution. includeArchived `string` (optional) Include archived facilities in the organisation analytics (default false).

Endpoint

GET /api/admin/saas-billing/org/{organisationId}/analytics

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/org/{organisationId}/analytics \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Reconcile an incoming payment against its money artifact by universal payment reference (XXXX-XXXX). Resolves wallet top-ups, top-up invoices (credits the wallet exactly once) and monthly records (marks paid). Idempotent — matching a settled reference is a reported no-op. Super-admin only.

Parameters

body `string` (optional) { reference: 'XXXX-XXXX', amountCents?: number (verified against the artifact when provided), paidAt?: unix seconds, source?: e.g. 'bank-transfer'|'ai-matcher', notes?: string, force?: boolean (override an amount mismatch) }

Endpoint

POST /api/admin/saas-billing/payments/match

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/payments/match \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Platform-wide billing and revenue analytics for the Insights tab: MRR and growth, billed vs collected vs outstanding by month, AR aging, revenue by category and organisation, net-revenue movement, billed units, billing-run health, prepaid wallet float, and Model Router spend. Super-admin only. Cached in-process for 5 minutes.

Parameters

months `string` (optional) Lookback window in months (default 12, max 24). refresh `string` (optional) Pass 1 to bypass the in-process cache. includeArchived `string` (optional) Include archived facilities in all analytics (default false).

Endpoint

GET /api/admin/saas-billing/platform-analytics

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/platform-analytics \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

The persisted platform-wide rate block (reserved org 'PLATFORM'), or the code defaults when none has been saved yet. Super-admin only.

Endpoint

GET /api/admin/saas-billing/platform-rates

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/platform-rates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert the platform-wide rate block. All charge keys must be non-negative numbers; chargeAdjustments is optional (percent / amountOffPerUnit / includedUnits per charge key). Changes take effect from the next daily billing log — never retroactively. Super-admin only.

Parameters

body `string` (optional) { charges: { pricePerGBStored, ... }, chargeAdjustments?: { : { type, value, label } } }

Endpoint

PUT /api/admin/saas-billing/platform-rates

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/saas-billing/platform-rates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all pricing templates (reserved org 'TEMPLATE'). Super-admin only.

Endpoint

GET /api/admin/saas-billing/rate-templates

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/rate-templates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a pricing template. Requires a name plus a full charges object; chargeAdjustments, cloudAgents and customCharges are optional. Super-admin only.

Parameters

body `string` (optional) { name, description?, charges: { pricePerGBStored, ... }, chargeAdjustments?: { : { type, value, label } }, customCharges?: [{ id?, label, amount, conditions[] }] }

Endpoint

POST /api/admin/saas-billing/rate-templates

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/rate-templates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Duplicate a pricing template. The copy carries the source's rates, discounts, cloud-agent overlay and custom charges, but starts with an empty change log and no linked blocks. Names itself " (copy)" (stepping to "(copy 2)" on collision) unless the body supplies a name. Super-admin only.

Parameters

templateId `string` (required) body `string` (optional) { name? } — omit to take the auto-generated copy name.

Endpoint

POST /api/admin/saas-billing/rate-templates/{templateId}/duplicate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/saas-billing/rate-templates/{templateId}/duplicate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a pricing template (name, charges, chargeAdjustments, cloudAgents and/or customCharges). Fields the request omits keep their stored value, so a rates-only save never wipes custom charge rules. Prior versions are preserved in the template's changeLog, and the new values fan out to every rate block still following the template. Super-admin only.

Parameters

templateId `string` (required) body `string` (optional) { name, description?, charges, chargeAdjustments?, cloudAgents?, customCharges? }

Endpoint

PUT /api/admin/saas-billing/rate-templates/{templateId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/saas-billing/rate-templates/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Soft-delete a pricing template. Blocks still linked to it are detached (they keep their current values). Super-admin only.

Parameters

templateId `string` (required)

Endpoint

DELETE /api/admin/saas-billing/rate-templates/{templateId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/saas-billing/rate-templates/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get list of active services (Super Admin only)

Retrieve list of services that have logged API calls in the past 7 days. Used to populate service selector in dashboard. Super admin access required.

Endpoint

GET /api/admin/service-logs/active-services

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/service-logs/active-services \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Query multi-service API logs (Super Admin only)

Query and filter API logs from multiple services (partner-api, universal-api, etc.) with advanced filtering capabilities. Super admin access required.

Request Body

Endpoint

POST /api/admin/service-logs/query

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/service-logs/query \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get cached multi-service log statistics from Redis (Super Admin only)

Retrieve aggregated statistics from Redis cache for instant dashboard loading. Falls back to DynamoDB if cache miss. Super admin access required.

Parameters

serviceId `string` (optional) Service ID to get statistics for (required) timeWindow `string` (optional) Time window for statistics (defaults to 24h)

Endpoint

GET /api/admin/service-logs/statistics

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/service-logs/statistics \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get time series data for timeline chart (Super Admin only)

Retrieve time-bucketed request/error counts for rendering timeline charts. Super admin access required.

Parameters

serviceId `string` (required) Service ID to get time series for (e.g., 'partner-api', 'universal-api') timeWindow `string` (optional) Time window for time series data (defaults to 24h)

Endpoint

GET /api/admin/service-logs/timeseries

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/service-logs/timeseries \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Find clubs with missing additional charges for a given month. This helps identify clubs that should have had region-based additional items applied but didn't (due to the localisation.country bug).

Parameters

month `string` (required) The billing month to check in YYYY-MM format organisationId `string` (optional) Optional organisation ID to filter clubs countryIso `string` (optional) Optional country ISO code to filter clubs (e.g. JP, AU) limit `integer` (optional) Maximum number of clubs to return in the results update `boolean` (optional) If true, adds missing charges to the CCTV billing record for the first day of the given month

Endpoint

GET /api/admin/tasks/backfill-missing-billing-base-charges

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/backfill-missing-billing-base-charges \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add organisation IDs to billing-related records for the new role integration.

Endpoint

GET /api/admin/tasks/billing-migrations

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/billing-migrations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Start the brand regions migration task

Endpoint

GET /api/admin/tasks/brand-regions-migration

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/brand-regions-migration \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually forces GymMaster to start 'syncing' all member data

Endpoint

GET /api/admin/tasks/build-peak-time-insights

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/build-peak-time-insights \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Start the cache mms users cron job.

Parameters

facilityIds `string` (optional) Optional list of facility IDs to cache the users for. userIds `string` (optional) Optional list of user IDs to cache the users for. checkCache `string` (optional) Optional flag to check the cache before querying the database.

Endpoint

GET /api/admin/tasks/cache-mms-users

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/cache-mms-users \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually triggers the CCTV heatmap pregeneration Lambda which fans out SQS messages per device to generate heatmaps.

Endpoint

GET /api/admin/tasks/cctv-heatmap-pregeneration

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/cctv-heatmap-pregeneration \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually triggers the CCTV retention cleanup Lambda (timelapse + AI metadata older than club retention).

Endpoint

GET /api/admin/tasks/cctv-retention-cleanup

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/cctv-retention-cleanup \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete old audit logs (Global Admin only)

Remove audit logs older than specified days (default 90 days) for log rotation/management

Request Body

Endpoint

POST /api/admin/tasks/cleanup-old-audit-logs

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/tasks/cleanup-old-audit-logs \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Run stripe daily payments report cron

Endpoint

GET /api/admin/tasks/daily-payments-report

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/daily-payments-report \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Save a daily saas billing log to DynamoDB for all clubs

Endpoint

GET /api/admin/tasks/daily-saas-billing-log

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/daily-saas-billing-log \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete notifications older than 30 days to improve performance

Endpoint

GET /api/admin/tasks/delete-old-notifications

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/delete-old-notifications \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Triggers club variables function

Parameters

clubId `string` (optional)

Endpoint

GET /api/admin/tasks/clubs/{clubId}/variables

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/clubs/{clubId}/variables \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Triggers low battery duress notifications for all clubs.

Parameters

clubId `string` (optional)

Endpoint

GET /api/admin/tasks/low-battery-duress-notifs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/low-battery-duress-notifs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

One-off migration that rewrites legacy moduleIds (e.g. ai-model-access -> ai-credits) stored in organisations, brands, club preferences and roles. Runs as a dry-run by default; pass ?apply=true to persist changes.

Parameters

apply `boolean` (optional) When true, persists changes. Otherwise only reports what would change.

Endpoint

GET /api/admin/tasks/migrate-module-ids

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/migrate-module-ids \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add default ids, objects, etc for the new role integration.

Endpoint

GET /api/admin/tasks/role-migrations

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/role-migrations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Checks for unscheduled sms and schedule them, unless the send date has already passed in which case send the sms immediately

Endpoint

GET /api/admin/tasks/sms-schedule

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/sms-schedule \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually trigger a full directory sync for all enabled facilities.

Endpoint

GET /api/admin/tasks/start-directory-sync

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/start-directory-sync \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Start the monthly biller cron job.

Parameters

clubID `string` (optional) Optional club ID to run the monthly biller for. forceBilling `string` (optional) Optional flag to force billing for the club. billingMonth `string` (optional) Optional billing month to run the monthly biller for in the format YYYY-MM. simulationTime `string` (optional) Optional unix timestamp to simulate the cron job running at. This will override the billing month. organisationId `string` (optional) Optional organisation ID to run the monthly biller for.

Endpoint

GET /api/admin/tasks/monthly-biller

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/monthly-biller \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually forces GymMaster to start 'syncing' all member data

Endpoint

GET /api/admin/tasks/sync-gm-data

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/sync-gm-data \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually forces GymMaster to start 'syncing' revenue history for our clubs

Parameters

startDate `string` (optional) Start date to report from (YYYY-MM-DD format). endDate `string` (optional) End date to report to (YYYY-MM-DD format).

Endpoint

GET /api/admin/tasks/sync-gm-revenue-history

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/sync-gm-revenue-history \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update all clubs yext data.

Endpoint

GET /api/admin/tasks/update-all-clubs-yext-data

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/update-all-clubs-yext-data \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually starts updating the holiday hours of all clubs

Endpoint

GET /api/admin/tasks/club-holidays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/club-holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually starts updating the holidays of all countries

Endpoint

GET /api/admin/tasks/country-holidays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/country-holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually starts the cron that auto publishes 5 star reviews to our club pages

Endpoint

GET /api/admin/tasks/published-reviews

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/published-reviews \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually forces our cron to update club social reviews...

Endpoint

GET /api/admin/tasks/update-social-reviews

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/update-social-reviews \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get all modules available to a facility

Invokes the facility-modules Lambda to return modules for the given facility (facility preferences → brand → organisation hierarchy).

Parameters

facilityId `string` (required) The facility (club) ID.

Endpoint

GET /api/admin/tasks/facilities/:facilityId/modules

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/tasks/facilities/:facilityId/modules \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get effective modules for a facility

Returns all modules available to a facility by resolving the hierarchy: facility preferences → brand modules → organisation modules. Results are cached in Redis for performance.

Parameters

facilityId `string` (required) The facility ID to resolve modules for

Endpoint

GET /api/facilities/{facilityId}/modules

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/modules \
  -H "x-api-key: YOUR_API_KEY"

Response

[]

Returns the module catalog plus the side-menu rendering config. The full module list is returned (including globalAdminOnly entries) so the front-end renderer can decide visibility per user; ACL is still enforced server-side via `auth.checkModuleAccess()`.

Endpoint

GET /api/modules

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/modules \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Sends a notification to all clubs that have failed payments.

Parameters

fromDate `string` (optional) Unix timestamp toDate `string` (optional) Unix timestamp

Endpoint

POST /api/admin/tasks/send-failed-club-payments-notif

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/tasks/send-failed-club-payments-notif \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates all club payment intents for the last 14 days.

Endpoint

PUT /api/admin/tasks/update-all-club-failed-payments-for-14-days

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/tasks/update-all-club-failed-payments-for-14-days \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List the stripe connected account details for all clubs in an organisation

Parameters

organisationId `string` (required)

Endpoint

GET /api/clubs/stripe/connected-account

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/stripe/connected-account \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List stripe records of club.

Parameters

club `string` (required) fromDate `string` (optional) Unix timestamp toDate `string` (optional) Unix timestamp socketID `string` (required) Unique identifier for socket request

Endpoint

GET /api/club/{club}/stripe/records

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/records \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Cancel a payment intent

Parameters

club `string` (required) paymentIntent `string` (optional)

Endpoint

GET /api/club/{club}/stripe/payment-intent/:paymentIntent/cancel

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/payment-intent/:paymentIntent/cancel \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a Stripe Account Session for embedded components

Creates a Stripe Account Session for a connected account. Returns a client_secret used to initialize Connect embedded components (disputes, payouts, account management, documents).

Request Body

Endpoint

POST /api/stripe/account-session

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/stripe/account-session \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Enables Apple Pay and Google Pay

Parameters

club `string` (required)

Endpoint

GET /api/club/{club}/stripe/enable-apple-pay-google-pay

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/enable-apple-pay-google-pay \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generates a one-time-link for the Stripe KYC page for a connected account.

Parameters

club `string` (required)

Endpoint

GET /api/club/{club}/stripe/generate-kyc-token

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/generate-kyc-token \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieve a payment intent from stripe.

Parameters

paymentIntentId `string` (optional)

Endpoint

GET /api/stripe/payment-intents/{paymentIntentId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/stripe/payment-intents/{paymentIntentId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

returns the platform stripe account id

Endpoint

GET /api/stripe/platform-connected-account-id

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/stripe/platform-connected-account-id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

returns the stripe publishable key

Endpoint

GET /api/stripe/publishable-key

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/stripe/publishable-key \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List stripe balance transactions of club.

Parameters

club `string` (required) payout `string` (optional) type `string` (optional)

Endpoint

GET /api/club/{club}/stripe/balance-transactions

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/balance-transactions \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List stripe payment intents of club.

Parameters

club `string` (required) fromDate `string` (optional) Unix timestamp toDate `string` (optional) Unix timestamp

Endpoint

GET /api/club/{club}/stripe/payment-intents

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/payment-intents \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List stripe payouts of club.

Parameters

club `string` (required) fromDate `string` (optional) Unix timestamp toDate `string` (optional) Unix timestamp

Endpoint

GET /api/club/{club}/stripe/payouts

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/payouts \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List club stripe charges.

Parameters

club `string` (required) fromDate `string` (optional) Unix timestamp toDate `string` (optional) Unix timestamp

Endpoint

GET /api/club/{club}/stripe/charges

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/charges \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets the account details for a Stripe connected account as part of the KYC process.

Parameters

club `string` (required)

Endpoint

GET /api/club/{club}/stripe/connect-account-details

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/{club}/stripe/connect-account-details \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Live Services running on a facility's AI Agent (publish picker)

Fetches the device's bridge-detected Live Services over the tunnel for the applet's "Publish to Performance Hub" picker. Requires the ph-ai-agent module AND 'open' per-device access (same bar as publishing itself). Each service is annotated with publishedAppId when a Custom App already exists for its port.

Parameters

club `string` (required) device `string` (required)

Endpoint

GET /api/agent-apps/services/{club}/{device}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/services/{club}/{device} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

MDI icon name index baked into a facility's AI Agent (icon picker)

Proxies the device bridge's baked MDI icon index (GET /__services/icons/mdi/index.json) over the tunnel. The publish/edit picker uses the applet's bundled catalog (same 7.4.47 pin); published-app SVGs are resolved from portal-server's local @mdi/js pack. Same access bar as the services picker (ph-ai-agent module + 'open' per-device access).

Parameters

club `string` (required) device `string` (required)

Endpoint

GET /api/agent-apps/mdi-index/{club}/{device}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/mdi-index/{club}/{device} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Fetch a batch of MDI icon SVGs from a facility's AI Agent (picker previews)

Resolves up to 60 named MDI glyphs from the device's baked icon set in one call, sanitised server-side with the same allowlist applied to persisted app icons. Used by the icon picker to render search results; unknown names come back null.

Parameters

club `string` (required) device `string` (required)

Request Body

Endpoint

POST /api/agent-apps/mdi-icons/{club}/{device}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/mdi-icons/{club}/{device} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Audience scopes the requester may publish to from this facility

The publisher's grantable audience envelope for the publish/edit picker: the facilities their ph-ai-agent roles reach (multi-facility scope), plus whether they hold the organisation-level standing required for whole-brand / whole-organisation audiences at this facility's brand/org. The same rules are re-enforced server-side on publish/update (validatePublishAudience) — this endpoint only shapes the UI.

Parameters

club `string` (required)

Endpoint

GET /api/agent-apps/audience-options/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/audience-options/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Autocomplete peers for a named-users app audience

Searches ONLY the users the requester can already see — people whose roles overlap at least one facility/region/organisation of the requester's own ph-ai-agent access. A minimum 2-character query and a 10-result cap keep the endpoint useless for scraping; the same reachability set is re-enforced server-side when the audience is saved.

Parameters

club `string` (required) q `string` (required)

Endpoint

GET /api/agent-apps/user-search/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/user-search/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Publish an AI Agent Live Service as a Performance Hub Custom App

Registers a web app hosted by the facility's AI Agent (a bridge-detected Live Service) as a "Custom Apps" side-menu item for the chosen audience. Requires the ph-ai-agent module at this facility AND 'open' per-device access; the audience is capped by the publisher's own role scopes (you can never publish wider than you can reach). Service identity is resolved LIVE from the device's /__services list; the http/https scheme is never persisted.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-apps/publish/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/publish/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Published Custom Apps visible at this facility

Returns the active published apps whose audience covers this facility, in the shape the side menu renders (appId, name, icon, description). Audience is re-resolved live on every call so access changes take effect immediately.

Parameters

club `string` (required)

Endpoint

GET /api/agent-apps/menu/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/menu/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Published apps managed from this facility (publisher view)

Full app rows for apps whose HOME facility is this club, for the applet's "Published Apps" manage list. Each row is annotated with canManage for the requesting user (publisher or global admin).

Parameters

club `string` (required)

Endpoint

GET /api/agent-apps/manage/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/manage/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Mint a service-scoped viewer token for a published Custom App

Returns a short-lived signed URL + token the browser uses to open ONE published app directly on the device's regional relay gateway. The token carries a svc claim naming the service port, so the gateway confines the session to /__services/proxy// — the agent chat/terminal is never reachable with it. Viewers need the custom-apps module at a facility the app's audience covers; they do NOT need the ph-ai-agent module or per-device agent access.

Parameters

club `string` (required) appId `string` (required)

Endpoint

POST /api/agent-apps/access/{club}/{appId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/access/{club}/{appId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Support attribution for a published Custom App (owner contact)

Who supports this user-published app: the publisher's email (falling back to the hosting agent's owner). Shown on the viewer's offline/error panels so support requests go to the app's owner instead of Performance Hub — published apps are not part of PH core support. The app's audience is re-checked first; viewers the app was never shared with learn nothing. Paused apps still resolve (owners field "why is this paused?" questions too).

Parameters

club `string` (required) appId `string` (required)

Endpoint

GET /api/agent-apps/support-info/{club}/{appId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-apps/support-info/{club}/{appId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Email a support request to a published Custom App's owner

Sends the viewer's message to the app's support contact (publisher, falling back to the agent owner) as a branded email — To the owner, CC the viewer (their record of the request), Reply-To the viewer so the owner replies straight to them. Published apps are user-maintained, so this keeps their support off Performance Hub's queue. Audience is re-checked; one request per viewer per app per 15 minutes (Redis cooldown, fail-open).

Parameters

club `string` (required) appId `string` (required)

Request Body

Endpoint

POST /api/agent-apps/support-request/{club}/{appId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/support-request/{club}/{appId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Update a published Custom App (name, icon, description, status, audience)

Publisher (or global admin) only. Audience changes are re-validated against the EDITOR's role scopes with the same capping rules as publish. Status toggles between active and paused (paused apps vanish from menus and refuse mints).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-apps/update/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/update/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Unpublish a Custom App (soft delete)

Publisher (or global admin) only. Soft-deletes the registry row - the app disappears from menus immediately and viewer mints refuse; already-issued gateway sessions lapse at token expiry.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-apps/unpublish/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/unpublish/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Transfer ownership of a published Custom App

Mirrors the AI Agent reallocate-owner flow: the current publisher, an account owner (billing module) or a global admin may hand the app to another user, who then manages it. The new owner must have facility access at the app's home club.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-apps/transfer-owner/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-apps/transfer-owner/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Staged skill exports on a facility's AI Agent (share picker)

Proxies the device bridge's staged-export list (GET /__skills/exports) over the tunnel for the applet's "Share a skill" picker. Exports are staged by the on-device ph-skill-sharing security/portability pass; each entry carries the device-side scan outcome. Requires the ph-ai-agent module AND 'open' per-device access (the same bar as publishing itself).

Parameters

club `string` (required) device `string` (required)

Endpoint

GET /api/agent-skills/exports/{club}/{device}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/exports/{club}/{device} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Publish a staged skill export as a NEW shared skill (draft version)

Pulls the named staged export tarball from the device bridge over the tunnel, extracts it in memory (path traversal/symlinks/oversize rejected), runs the cloud-side deterministic security scan, builds the manifest from the SKILL.md frontmatter, stores the tarball content-addressed in the private skills bucket and creates the skill head + a DRAFT version. A scan block persists NOTHING and returns the findings. The audience is capped by the publisher's own role scopes. Submit the draft (POST submit) to publish it.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/publish/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/publish/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Publish a staged export as a NEW VERSION of an existing shared skill

Same pipeline as publish, against an existing skill: the export's SKILL.md name must match the skill, the version must be new (versions are immutable), and a changelog is required. Only the publisher (or a global admin) may add versions. A scan block persists a status 'rejected' version row (report only, no artifact) so the findings show in the publisher's history.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/new-version/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/new-version/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Full scan report (+ LLM review) for one skill version

The complete findings list for a version — publisher, organisation admins (approval reviews) and global admins only; installers see the summarised counts on the skill detail instead.

Parameters

club `string` (required) skillId `string` (required) version `string` (required)

Endpoint

GET /api/agent-skills/scan-report/{club}/{skillId}/{version}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/scan-report/{club}/{skillId}/{version} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Submit a draft skill version (publish, or queue for approval)

Moves a draft version forward per the organisation's governance. When the org has opted into LLM review the instruction review runs first (best-effort; a 'fail' verdict rejects, a 'flag' verdict forces the approval queue). Facility- tier shares publish immediately unless governance requires approval; org- library shares (brand/organisation audience) default to requiring approval. Publishing sets the skill's latestVersion — 'auto'-policy installs pick it up on the next reconcile sweep.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/submit/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/submit/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delist a shared skill (removes it from the library)

Publisher (or global admin) only. The skill disappears from the library and refuses new installs immediately; EXISTING installs keep working — delisting is a listing action, not a kill switch (use /api/agent-skills/admin/revoke for that).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/delist/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/delist/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Edit a shared skill's listing (display name, description, icon)

Publisher (or global admin) only. Presentation-only fields — the canonical skill name is its identity (manifests, install dirs, version matching) and never changes. An empty string clears a field back to null (falling back to the canonical name / no icon). Icons use the MDI catalog (mdi:icon-name), the same format as published agent apps.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/update-listing/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/update-listing/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Transfer ownership of a shared skill

Mirrors the published-apps transfer flow: the current publisher, an account owner (billing module) or a global admin may hand the skill to another user, who then manages its versions and listing. The new owner must have facility access at the skill's home club.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/transfer-owner/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/transfer-owner/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Skill library visible at this facility (audience-filtered)

Active skills with at least one published version whose audience covers this facility (or names the viewer), annotated with the latest published version summary and the org-adoption footprint (distinct facilities, never raw install counts). Audience is re-resolved live on every call.

Parameters

club `string` (required)

Endpoint

GET /api/agent-skills/library/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/library/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Skill detail (versions, requirements, scan summary, adoption)

Full detail for one library skill: version history with changelogs and scan summaries (per-version endpoint lists power the update scan-diff), declared requirements from the manifest, publisher provenance and the facility-count adoption signal. The audience is re-checked — viewers a skill was never shared with learn nothing (the publisher and org admins always see it).

Parameters

club `string` (required) skillId `string` (required)

Endpoint

GET /api/agent-skills/skill/{club}/{skillId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/skill/{club}/{skillId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Skills published from this facility (publisher's manage list)

Full skill rows whose HOME facility is this club, each annotated with canManage for the requesting user and its latest version summary (drafts and pending approvals included — this is the publisher's working view).

Parameters

club `string` (required)

Endpoint

GET /api/agent-skills/manage/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/manage/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Install a library skill onto a facility's AI Agent

Governance-gated: the org's installSources must allow it, the skill's audience must cover this facility (or name the requester), the version must be published, and the requester must clear the whoCanInstall tier for the target device (owner / allowed user / facility admin / org admin — see governance). Writes the install lifecycle row (the source of truth) and makes an immediate best-effort push; the reconcile cron guarantees delivery once the device is reachable.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/install/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/install/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Approve a pending skill update for one install

Moves the install's desiredVersion to the latest published version (the 'notify' and 'pinned' policies' manual step, and the path when governance sets updatePosture 'approvalRequired'). Keeps the current version as the one-step rollback target and clears any post-rollback update pin (skipVersion). Same whoCanInstall permission tier as install.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/update-approve/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/update-approve/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Roll an installed skill back to its previous version

Sets desiredVersion to the install row's previousVersion (kept on every version move) and lets the normal delivery path re-install it. One-step: the versions swap, so rolling back twice returns to where you started. Also pins updates (skipVersion = the version rolled back from) so the auto/notify policies leave the rollback in place — the pin clears when a strictly newer version publishes, on update-approve, or on set-policy.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/rollback/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/rollback/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Uninstall a skill from a facility's AI Agent

Marks the install row pending-uninstall and pushes the desired state; the row is deleted once the device confirms removal (reconcile read-back). Same whoCanInstall permission tier as install.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/uninstall/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/uninstall/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Set the per-install update policy for a skill on one device

auto (reconcile applies new published versions automatically, unless the org's updatePosture requires approval), notify (owner is notified once per new version and applies it manually) or pinned (never moves without an explicit update-approve). Changing the policy clears any post-rollback update pin (skipVersion). Same whoCanInstall permission tier as install.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/set-policy/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/set-policy/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Skill installs on a facility's AI Agent (Skills tab)

The install lifecycle rows for one device, each annotated with the skill's listing fields and whether a newer published version exists. Requires 'open' per-device access (the Skills tab lives inside the agent drawer).

Parameters

club `string` (required) device `string` (required)

Endpoint

GET /api/agent-skills/installs/{club}/{device}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/installs/{club}/{device} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Skill versions awaiting approval in this facility's organisation

The org-admin approval queue: every pending-approval version across the organisation's skills, with the skill listing and scan/LLM summaries. Organisation admins (or global admins) only.

Parameters

club `string` (required)

Endpoint

GET /api/agent-skills/approvals/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/approvals/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Approve a pending skill version (publishes it)

Organisation admins (or global admins) only. The version becomes published, the skill's latestVersion moves, and the publisher is notified. 'auto'-policy installs pick the version up on the next reconcile sweep.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/approve/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/approve/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Reject a pending skill version

Organisation admins (or global admins) only. The version becomes rejected with the reviewer's reason and the publisher is notified — they can fix the findings and submit a new version (versions are immutable).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/reject/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/reject/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Effective Agent Skill governance for this facility's organisation

The stored per-org policy merged over the platform defaults (an org with no stored row sees pure defaults). Organisation admins (or global admins) only.

Parameters

club `string` (required)

Endpoint

GET /api/agent-skills/governance/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/agent-skills/governance/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update Agent Skill governance for this facility's organisation

Partial update — only the supplied fields move; everything else keeps its stored/default value. Organisation admins (or global admins) only. Per-device overrides live on the registration row via the existing device config routes.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/agent-skills/governance/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/governance/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Kill switch — revoke a skill version and quarantine every install

Global admins only. Marks the named version (or EVERY published version when omitted) revoked, recomputes the skill's latestVersion, and fans a desired action 'quarantine' with the reason across every affected install (skillId GSI) — the device moves the skill aside (never silently deletes) on the next push/reconcile. Each install's device owner is notified.

Request Body

Endpoint

POST /api/agent-skills/admin/revoke

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/agent-skills/admin/revoke \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get environment data for a facility

Returns current weather conditions including sunrise/sunset (via Open-Meteo) and indoor facility temperature (from duress sensors) for the specified club. Cached in Redis for 30 minutes.

Parameters

clubId `string` (required) Internal ID of the club/facility

Endpoint

GET /api/clubs/{clubId}/environment

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubId}/environment \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/associates a generic IoT device with a club.

Parameters

club `string` (required) Internal ID of the club that you wish to add the device under. body `string` (required) Json Object of the new screen to associate with.

Endpoint

POST /api/devices/addGenericDevice/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/addGenericDevice/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remove and factory-reset a display screen

Removes the screen's active facility association and arms a durable factory reset. A powered-off screen applies the reset after it next powers on and reconnects, then returns to its HDMI pairing page. Historical billing records are retained.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/display-screens/reset/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/display-screens/reset/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Associates a door controller with a facility.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/door-controllers/associate/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/door-controllers/associate/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Updates door controller settings for a facility.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/door-controllers/update/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/door-controllers/update/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Decommissions a door controller from a facility.

Parameters

club `string` (required)

Endpoint

POST /api/devices/door-controllers/decommission/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/door-controllers/decommission/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the relay configuration for a door controller.

Parameters

uuid `string` (required)

Endpoint

GET /api/devices/door-controllers/config/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/door-controllers/config/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the metadata of the device

Parameters

uuid `string` (required) Unique ID of the device

Endpoint

GET /api/devices/metadata/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/metadata/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the metadata of the device. Response is the metadata row at the top level (legacy shape) plus `detectedType` (camera | ai-edge-processor | door-controller | ph-ai-agent | null) and `online` (true when updated within 5 minutes).

Parameters

deviceSerialNumber `string` (required) Serial Number of the device

Endpoint

GET /api/devices/metadata/serial/{serialNo}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/metadata/serial/{serialNo} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the smart club data for the club.

Parameters

club_id `string` (required) Internal ID of the club that you wish to add the device under.

Endpoint

GET /api/clubs/{club_id}/smart-club-data

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club_id}/smart-club-data \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all devices associated with an individual club.

Parameters

club `string` (required) Internal ID of the club that you wish to list devices from.

Endpoint

GET /api/devices/list/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/list/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all application releases (versions) for our balena devices..

Endpoint

GET /api/devices/listReleases

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/listReleases \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Moves a device to a new facility (club) and updates related systems.

Parameters

club `string` (required) Source facility ID (current club the device is in) body `object` (required) Move parameters

Endpoint

POST /api/devices/move/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/move/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Attempts to establish a connection to a facility's router by selecting the best in-club device and sending an MQTT command to create a tunnel.

Parameters

facilityID `string` (required) Internal ID of the facility for which the router connection is being attempted.

Endpoint

GET /api/devices/openRouterWebpage/{facilityID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/openRouterWebpage/{facilityID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Cloud agent catalog (zones, sizes, live sell prices)

Parameters

club `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/cloud/catalog/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/catalog/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Quote a cloud agent (software + hosting)

Endpoint

POST /api/devices/ph-ai-agent/cloud/quote/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/quote/{club} \
  -H "x-api-key: YOUR_API_KEY"

Launch a cloud agent (enqueue provision + auto-associate)

Endpoint

POST /api/devices/ph-ai-agent/cloud/launch/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/launch/{club} \
  -H "x-api-key: YOUR_API_KEY"

Cloud agent job status

Endpoint

GET /api/devices/ph-ai-agent/cloud/jobs/{club}/{jobId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/jobs/{club}/{jobId} \
  -H "x-api-key: YOUR_API_KEY"

Purge a cloud agent (VM + balena + registration)

Endpoint

POST /api/devices/ph-ai-agent/cloud/delete/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/delete/{club} \
  -H "x-api-key: YOUR_API_KEY"

Resolve a parked cloud agent removal (retry backup, delete without backup, or cancel)

Endpoint

POST /api/devices/ph-ai-agent/cloud/delete-decision/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/cloud/delete-decision/{club} \
  -H "x-api-key: YOUR_API_KEY"

Platform cloud-agent catalog (super-admin)

Endpoint

GET /api/admin/devices/ph-ai-agent/cloud/catalog

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/devices/ph-ai-agent/cloud/catalog \
  -H "x-api-key: YOUR_API_KEY"

List an agent's Connected Apps (suites + apps with connected accounts)

Returns the agent's Connected Apps state: the enabled flag, per-suite rollups (Google Workspace, Microsoft 365) and the curated app catalog with each app's connected accounts (multi-account — an agent can hold several accounts per app, each with an optional alias) resolved from the agent's upstream session.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Endpoint

GET /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Full Connected Apps marketplace catalog for an agent

Returns every connectable app (the full managed-auth toolkit catalog, cached server-side for ~12h) with featured/suite tiers and the agent's connected accounts per app, plus per-suite rollups and the agent's pending connect requests — one payload for the client-side-searchable apps marketplace.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Endpoint

GET /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/catalog

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/catalog \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Dismiss a pending agent connect request

Marks the agent's pending connect request for a toolkit as dismissed (it disappears from the marketplace's "Requested by your agent" section). Idempotent — dismissing a request that isn't pending is a no-op.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/requests/dismiss

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/requests/dismiss \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Enable or disable Connected Apps for an agent

Persists the agent's Connected Apps switch and pushes the PH_APPS_MCP_ENABLED Balena device variable to that one device (best-effort — the PH-side flag is the hard gate on the MCP relay).

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/enable

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/enable \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Connect preparation payload for one app (mode, credential fields, setup guide)

Everything the connect dialog needs before starting a connection: how the app connects (oauth = hosted consent flow, credentials = in-product form), the credential fields to collect for credentials mode, and the in-product setup guide (authored for priority apps, otherwise generated from the app's field metadata — never a link to external docs). Bring-your-own OAuth apps also carry whether the customer's OAuth app is registered for THIS agent yet (byoConfigured) and the redirect URL to register with the provider.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID. toolkit `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-info/{toolkit}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-info/{toolkit} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Connect an app with user-supplied credentials (API key etc., no OAuth)

Creates a connected account for a credentials-mode app straight from the in-product form — no hosted consent flow. The credential fields come from the app's connect-info payload; every required field must be supplied. Credentials are validated with the provider where supported (best-effort — some apps only reject a wrong key on the agent's first tool call). An optional alias labels the new account (multi-account — connecting an already connected app adds ANOTHER account).

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-credentials

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-credentials \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Register the customer's own OAuth app for a BYO app and start its connect flow

For bring-your-own OAuth apps (Xero, Shopify, ...): takes the client ID and client secret of the OAuth app the customer created with the provider (walked through by the app's setup guide), registers it for THIS agent (the secret is stored only with the upstream integration platform — never in Performance Hub), and immediately starts the hosted sign-in flow against it. Returns the consent URL to send the user to, same contract as the connect endpoint. Re-submitting replaces the agent's registered app (e.g. after a secret rotation) — existing connected accounts keep working.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-oauth-app

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/connect-oauth-app \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Disconnect one connected account from an agent

Deletes a single connected account (multi-account — other accounts of the same app stay connected). The account is validated as belonging to this agent before deletion; when it was the app's LAST account the toolkit is removed from the agent's connected set (the session is lazily recreated so the agent's tool list updates).

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/disconnect

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/disconnect \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Rename (re-alias) one of an agent's connected accounts

Sets the display alias of a single connected account. Aliases are normally set automatically after OAuth (from the signed-in identity); this endpoint backs the manual rename in the app detail dialog. An empty alias clears the label. The account is validated as belonging to this agent before the upstream update.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/rename-account

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/rename-account \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Toggle a built-in Performance Hub service for an agent

Switches one always-on built-in service (Smart Search, Weather, ...) on or off for this agent. Built-ins need no connection or OAuth — they are included with every agent and on by default; this toggle persists the per-agent override and recreates the agent's upstream session immediately so the tool set updates. Note the separate "External apps" switch (the /enable route) is a hard off switch over the whole apps MCP server — when it is off, built-ins are unavailable too regardless of their individual toggles.

Parameters

facilityId `string` (required) deviceId `string` (required) The agent device's balena UUID. slug `string` (required) Built-in service slug.

Request Body

Endpoint

PATCH /api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/built-in/{slug}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/connected-apps/{facilityId}/{deviceId}/built-in/{slug} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Associate an AI Agent device with a facility

Metadata-first association. Looks up the device by serial in live device metadata, requires it to be online, then lazily creates the registration row, assigns a Chisel relay region + tunnel port + secret, registers that slot on the relay, and pushes the facility + tunnel config to the device via Balena. New devices are also seeded with a default MCP service account (enabled, scoped to this facility, all capabilities); re-pairing keeps any existing MCP grant. Optional advanced settings override the stamped defaults at pairing time — backup config, MCP on/off, access restriction — and `restoreFrom` seeds the new device from another facility device's cloud backup (active or decommissioned source; queues a cross-repo restore, returned as `restoreRequest` for progress polling).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/associate/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/associate/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List AI Agent devices for a facility

Returns the facility's AI Agent devices with live online + tunnel status (used by the applet device switcher).

Parameters

club `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/list/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/list/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

AI Agent update + online status

Returns whether the device is online, whether an update is available/pending, and the offered release (fleet pin when the fleet is pinned; highest successful when the fleet tracks latest).

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/update-status/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/update-status/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

AI Agent live device status + metrics

Returns a curated snapshot for the applet's metrics strip and management drawer: identity + registration fields, liveness + connection, software versions, and the latest heartbeat metrics (CPU, temperature, memory, per-mount storage, uptime, network). Flattens the device metadata beacon + Balena update status; either half may be missing on a transient outage.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/device-status/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/device-status/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

AI narrative for the device health report

Returns a short operator-facing explanation of the current derived health issues. Facts and playbook steps are always in device-status; this extra paragraph is best-effort and may be null.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

POST /api/devices/ph-ai-agent/health/{club}/{uuid}/explain

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/health/{club}/{uuid}/explain \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Mint a direct-to-relay access token for an AI Agent

Returns a short-lived signed URL the browser uses to connect DIRECTLY to the device's regional relay gateway (cutting the global PH/Sydney hop), plus the HS256 token. PH stays the authority (Google SSO + module/facility checks here); the relay-gateway verifies the token. The /ai-agent-ui proxy remains the fallback.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/access/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/access/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Send a chat message into an AI Agent session (notification inline reply)

Server-side relay used by the web push notification's inline reply action - the service worker POSTs here (same-origin, SSO cookies) so a reply works with no Performance Hub tab open. PH resolves the device's relay target (same lookup as the /ai-agent-ui proxy), stamps x-ph-user for turn attribution (the resulting completion push goes back to this user), and forwards to the device's /api/chat/start with the session id.

Request Body

Endpoint

POST /api/devices/ph-ai-agent/reply

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/reply \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Read an AI Agent's access-control settings (owner or super admin)

Returns the device's access block (mode, allowlist, visibility, PH Support toggle) plus any pending access requests. Readable by the device owner and by super admins (support, managing on the owner's behalf); other users get 403.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/access-settings/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/access-settings/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update an AI Agent's access-control settings (owner or super admin)

Write of mode (org/restricted), the restricted allowlist, list visibility (all/admins), and the "permit access from Performance Hub Support" toggle. Allowed for the device owner and for super admins acting on the owner's behalf (support; audit-logged). The owner itself can only be changed via reallocate-owner. Approved access requests are durable — still-approved requesters are unioned back into the saved allowlist; removing one from the submitted list revokes their approval (request flips to denied; they may request again).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/access-settings/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/access-settings/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Reassign an AI Agent's owner

Reassigns device ownership to another Performance Hub user. Restricted to account owners (SaaS billing module access) and super admins — the escape hatch when a restricted agent's owner leaves. Both the previous and the new owner are notified (in-app + push + email).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/reallocate-owner/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/reallocate-owner/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Facility user list for the AI Agent allowlist / owner pickers

Returns email + name (+ isOrgAdmin/isGlobalAdmin flags) for every user whose role gives them access to THIS facility. Gated to the device owner and reallocators (account owner / super admin) so regular users can't enumerate the user base. Global admins may pass scope=system to list every user in the system (allowlist picker in Super Admin Mode); non-global-admins get the facility scope regardless.

Parameters

club `string` (required) uuid `string` (required) scope `string` (optional) 'system' (global admins only) lists all users instead of this facility's.

Endpoint

GET /api/devices/ph-ai-agent/org-users/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/org-users/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Request access to a restricted AI Agent

Creates (or re-opens) the requester's access request for a restricted device — idempotent per user+device. The owner is notified over in-app, web push, and email with a deep link to the agent module.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/access-request/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/access-request/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Approve or deny an AI Agent access request (owner or super admin)

Resolution of a pending request by the device owner, or by a super admin on the owner's behalf (support; audit-logged). Approving appends the requester to the device's allowlist; either outcome notifies the requester (in-app + push + email).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/access-request-resolve/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/access-request-resolve/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Permit + apply an AI Agent update

Pins the device to the offered release (fleet pin, or highest successful when the fleet tracks latest) and releases the update lock so the balena supervisor applies it. State on the device's data volume survives the update.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/update/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/update/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Schedule an AI Agent update for later

Stores a scheduled install time on the device's registration. A recurring backend job (every 5 minutes) applies the update (pin + unlock) once the scheduled time passes. Scheduling replaces any existing schedule for the device.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/update-schedule/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/update-schedule/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Cancel a scheduled AI Agent update

Clears the pending scheduled install for the device (no-op when nothing is scheduled).

Parameters

club `string` (required) uuid `string` (required)

Endpoint

DELETE /api/devices/ph-ai-agent/update-schedule/{club}/{uuid}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/update-schedule/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Run a remote command on an AI Agent device

Publishes an allow-listed MQTT command (reboot, restart a container, lock/unlock updates, Wi-Fi management) to the device-controller running on the AI Agent. The device must be associated with the facility.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/command/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/command/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Update an AI Agent's facility-facing configuration

Persists operator-editable settings for an associated AI Agent: the device name, the physical device location, and the scheduled-reboot cadence. The reboot schedule is also pushed to the device as the REBOOT_DEVICE Balena env var (2am local time), matching the Coaching Screen behaviour.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/config/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/config/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Facilities an AI Agent at this facility can be moved to

Returns the same-organisation facilities the signed-in user can access (excluding the current facility), for the "Move to another facility" picker. The move itself is performed by POST /api/devices/move/:club, which enforces the same same-organisation + target-access rules server-side.

Parameters

club `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/move-targets/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/move-targets/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

The requester's grantable MCP access envelope for a facility's AI Agents

Returns what the signed-in user is allowed to grant to an AI Agent MCP service account at this facility's organisation: the facilities/regions within their own access, whether they may grant organisation-wide scope, the module universe they hold, and the full MCP tool catalog (for the advanced per-tool mask). The UI uses this so users only ever see options within their own permission envelope; the mcp-access POST endpoint enforces the same attenuation server-side.

Parameters

club `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/mcp-grantable/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/mcp-grantable/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get an AI Agent's MCP service-account configuration

Returns the device's MCP access config (scope, modules, tool mask, audit fields). The superAdmin flag is only included for global admin callers.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/mcp-access/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/mcp-access/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Configure an AI Agent's MCP service account

Saves the device's MCP access config with grant-time attenuation. Non-global-admin requesters can only grant facilities/regions within their own access, organisation scope only when they hold an organisation-wide role, and modules they themselves hold at the facility's organisation. The superAdmin flag is only accepted from global admins (preserved unchanged otherwise). The enabled flag is also pushed to the device as the PH_MCP_ENABLED Balena env var.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/mcp-access/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/mcp-access/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get an AI Agent's VPN configuration (redacted)

Returns the device's VPN support flag and connection list. Profile bodies and credential values are never returned — only import-time metadata (remotes, routes, DNS) and has-credential flags. Live per-connection state comes from the device-status endpoint (beacon metadata.vpn).

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/vpn-config/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-config/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Toggle an AI Agent's VPN support

Turns the device's VPN feature on/off. Pushes the PH_VPN_ENABLED balena device variable and nudges the device (MQTT vpnConfigChanged); connections are kept when toggled off (tunnels stop; config stays for re-enable).

Parameters

club `string` (required) uuid `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/vpn-config/{club}/{uuid}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-config/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Import OpenVPN profile(s) onto an AI Agent

Accepts base64-encoded uploads — single .ovpn/.conf, split-file bundles (config + certs/keys), and archives (.zip, .tar/.tgz Pritunl exports, .tblk Tunnelblick, .visc/.visz Viscosity). Profiles are normalised to a canonical inline form; each profile becomes one connection (imported disconnected — enter credentials, then connect). Actionable 400s on unusable uploads.

Parameters

club `string` (required) uuid `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/vpn-import/{club}/{uuid}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-import/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Update an AI Agent VPN connection (name / credentials / split-DNS)

Updates the stored connection. Credential fields are write-only (omitted = keep stored value; empty string = clear). Credential/split-DNS changes bump the connection revision so a live tunnel restarts with the new values.

Parameters

club `string` (required) uuid `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/vpn-connection/{club}/{uuid}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-connection/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete an AI Agent VPN connection

Removes the connection from the registration and nudges the device, which tears the tunnel down and purges its cached profile/credentials.

Parameters

club `string` (required) uuid `string` (required) connectionId `string` (required)

Endpoint

DELETE /api/devices/ph-ai-agent/vpn-connection/{club}/{uuid}/{connectionId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-connection/{club}/{uuid}/{connectionId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Connect / disconnect an AI Agent VPN connection

Desired-state model — sets the connection's enabled flag on the registration and nudges the device (payload-free MQTT vpnConfigChanged); the device pulls the authoritative state via its JWT-authenticated universal-api call and reconciles its tunnels. A missed nudge converges on the periodic sync.

Parameters

club `string` (required) uuid `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/vpn-command/{club}/{uuid}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/vpn-command/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get an AI Agent's cloud-backup configuration + status

Returns the device's backup settings (enabled, retention, storage region), the rolling backup status (last backup, size, errors), the resolved automatic region, and the available storage regions for the picker. The restic repo password is never returned.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-config/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-config/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update an AI Agent's cloud-backup configuration

Saves enabled/retention/region. Takes effect on the device's next hourly backup tick (the device asks PH for its run context before every run), so no device restart is involved.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/backup-config/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-config/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List backup restore sources for pairing a new AI Agent

Facility-wide view for the add-agent dialog's "restore from a backup" option: every registration in the club — active AND decommissioned/replaced — that still has a decryptable backup repo and at least one usable restore point, with its newest snapshots. Also returns the backup config option lists (allowedRetentionDays, availableRegions) so the dialog needs no device UUID to populate its selects.

Parameters

club `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-sources/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-sources/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List an AI Agent's backup restore points

Returns the device's snapshot index (newest first) from DynamoDB — no device or repo round-trip — plus the current manual-backup / restore request state for drawer polling. Stale requests (never picked up, or no progress heartbeat) are presented as failed so the UI can always submit a new one.

Parameters

club `string` (required) uuid `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-snapshots/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-snapshots/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Request a manual backup of an AI Agent now

Writes a manual-run request (with the user's note) onto the registration row and nudges the device over MQTT. The device fetches the verified request via its JWT-authenticated universal-api run-context call — even without MQTT it is picked up on the next scheduler tick. Rejected while another backup or restore is in flight.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/backup-run/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-run/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Pin or unpin an AI Agent restore point

Pinned restore points are protected from retention pruning — the device's nightly maintenance receives the pinned snapshot ids via its run-context call and excludes them from restic forget — and their index rows never TTL out. Unpinning restores the normal retention behaviour.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/backup-pin/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-pin/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Restore an AI Agent from a backup restore point

Writes a restore request onto the registration row and nudges the device. Full restores overwrite /data and /home/hermeswebui (the device first takes an automatic pre-restore safety snapshot and stops the agent during the restore) and require the device name typed as confirmation. Passing `paths` performs a non-disruptive file-level restore of just those paths instead. Optionally pins the device back to the snapshot's software release once the data restore completes (see backup-restore-release).

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/backup-restore/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-restore/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Apply the software release recorded on a completed restore

Final step of a restore that requested the snapshot's software version: once the device reports the data restore completed, this pins the device to the stored release and unlocks updates (same mechanics as the update endpoint). Driven by the drawer's polling; idempotent — the stored pin is cleared once applied.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/backup-restore-release/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-restore-release/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Browse files inside a backup restore point

Lists one directory level of a restic snapshot, served entirely server-side from the Wasabi repo (works with the device offline). Only tree metadata is read — no file data is downloaded for listings.

Parameters

club `string` (required) uuid `string` (required) takenAt `number` (required) path `string` (optional)

Endpoint

GET /api/devices/ph-ai-agent/backup-files/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-files/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search filenames inside a backup restore point

Case-insensitive filename search from a directory down, served server-side from the restic tree metadata (no file data is read; works with the device offline). Streams the listing and stops at the first 200 matches.

Parameters

club `string` (required) uuid `string` (required) takenAt `number` (required) q `string` (required) path `string` (optional)

Endpoint

GET /api/devices/ph-ai-agent/backup-search/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-search/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

What changed between two backup restore points

Runs a server-side restic diff between two of the device's snapshots (tree metadata only) and returns the added/removed/modified file list (capped at 500 changes) plus summary statistics. Results are cached — snapshots are immutable.

Parameters

club `string` (required) uuid `string` (required) fromTakenAt `number` (required) toTakenAt `number` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-diff/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-diff/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Version history of one file across all restore points

One server-side restic find across every snapshot in the device's repo, collapsed to DISTINCT versions (consecutive identical size+mtime hits are merged) and joined to the snapshot index rows for dates/kinds/notes.

Parameters

club `string` (required) uuid `string` (required) path `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-file-versions/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-file-versions/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search every restore point of a device's backups by file name

The deleted-file recovery path: one server-side restic find across ALL snapshots in the repo (case-insensitive, substring or glob), grouped by path with the restore points each file appears in. A file deleted from the device is still findable here as long as any restore point contains it.

Parameters

club `string` (required) uuid `string` (required) q `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-find/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-find/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Download a single file from a backup restore point

Streams one file straight out of the restic repo to the browser (attachment). Directories are streamed as a tar archive. Size-capped; served server-side, so it works with the device offline.

Parameters

club `string` (required) uuid `string` (required) takenAt `number` (required) path `string` (required)

Endpoint

GET /api/devices/ph-ai-agent/backup-file-download/{club}/{uuid}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/backup-file-download/{club}/{uuid} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Decommission an AI Agent from a facility

Parameters

club `string` (required)

Endpoint

POST /api/devices/ph-ai-agent/decommission/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/decommission/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remove an AI Agent from a facility and factory-reset the hardware

Fully disassociates the device so it can be paired at ANY facility, and wipes all data on the NUC. The wipe is armed via the PH_FACTORY_RESET balena device variable (a one-time nonce) BEFORE the cloud teardown, so it survives the device being offline at removal time — the wipe runs when it next connects. An MQTT factoryReset nudge makes the online case immediate. Cloud teardown then revokes every credential and grant, clears the Balena facility binding (device vars + club tag) and the metadata clubID, deletes access requests and the LAN DNS record. Cloud backups are RETAINED: the snapshot index and repo password stay on the soft-deleted registration, usable as a restore source when adding a replacement. Requires the device's name typed as confirmation.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/reset/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/reset/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Replace a dead AI Agent with a new NUC (disaster recovery)

One-shot device replacement: associates the replacement NUC (tunnel slot, secrets, balena vars, backup seed), carries over the old device's name, location, reboot schedule, backup settings, access block and MCP grant, re-keys the old snapshot index to the new device (so its full backup history stays browsable), decommissions the old registration (stamped replacedBy / replacedFrom), and — unless `restore` is false — queues a full restore of the chosen restore point from the OLD device's backup repo onto the new hardware. Works with the old device dead/offline; requires the old device's name typed as confirmation. Same-facility only.

Parameters

club `string` (required)

Request Body

Endpoint

POST /api/devices/ph-ai-agent/replace/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/devices/ph-ai-agent/replace/{club} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Resolves a Performance Hub device QR short link to the deep link it points at, so the Add Device scanner can detect the device type. Only performancehub.co / ubx.fit hosts are followed.

Parameters

url `string` (required) The scanned short link

Endpoint

GET /api/devices/resolve-qr

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/resolve-qr \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Tests the connectivity to a facilities Unifi Controller and if the credentials are correct.

Parameters

facilityID `string` (required) Internal ID of the facility that you wish to test unifi connectivity with

Endpoint

GET /api/devices/testUnifiController/{facilityID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/devices/testUnifiController/{facilityID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a generic IoT device with a club.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

PUT /api/devices/updateGenericDevice/{club}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/devices/updateGenericDevice/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Grant complimentary Model Router credit to a facility (super admin only)

Credits the facility's prepaid AI balance directly, with no card charge. Restricted to global admins. Recorded as an `adjustment` transaction with the granting admin's email and an optional note.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/clubs/{clubID}/ai-credits/admin/grant-credit

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/admin/grant-credit \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Facility Model Router summary (config, balance, spend).

Parameters

clubID `string` (required) tz `string` (optional) Viewer's IANA timezone — fallback for day/month spend windows when the facility has no timezone data.

Endpoint

GET /api/clubs/{clubID}/ai-credits/overview

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/overview \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Catalogue of available models with per-facility enabled state (default all enabled).

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/models

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/models \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Available guardrails and PH preset templates.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/guardrails

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/guardrails \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Connected Model Router services. Includes paired AI Agent devices, explicitly typed external agents, and the facility Workflow service. Configuration is edited via PATCH /keys/{keyHash}.

Parameters

clubID `string` (required) tz `string` (optional) Viewer's IANA timezone — fallback for day/month spend windows when the facility has no timezone data.

Endpoint

GET /api/clubs/{clubID}/ai-credits/agents

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/agents \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable Model Router for a facility (provisions its LiteLLM team).

Parameters

clubID `string` (required)

Endpoint

POST /api/clubs/{clubID}/ai-credits/enable

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/enable \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update plan, model allowlist, guardrails, content filters (PH-side regex redact/block), spend limit, and auto-recharge config.

Parameters

clubID `string` (required)

Endpoint

PATCH /api/clubs/{clubID}/ai-credits/config

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Reset the lifetime hard-cap counter to 0 (rebaseline to current spend) and log the closed period to history.

Parameters

clubID `string` (required)

Endpoint

POST /api/clubs/{clubID}/ai-credits/spend-limit/reset-total

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/spend-limit/reset-total \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Hard-cap reset history (newest first) — cap, spent, and timestamps per closed period.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/spend-limit/history

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/spend-limit/history \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a new phk_ API key for the facility (plaintext returned once). Accepts optional spend caps, model allowlist, guardrails, content filters, and rpmLimit/tpmLimit rate limits.

Parameters

clubID `string` (required)

Endpoint

POST /api/clubs/{clubID}/ai-credits/keys

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/keys \
  -H "x-api-key: YOUR_API_KEY"

Update editable key fields: label, per-key spend caps, model allowlist, guardrails, content filters, and rpmLimit/tpmLimit rate limits (synced to the backing LiteLLM key).

Parameters

clubID `string` (required) keyHash `string` (required)

Endpoint

PATCH /api/clubs/{clubID}/ai-credits/keys/{keyHash}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/keys/{keyHash} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Per-request inference logs for the facility (live from LiteLLM, metadata only).

Parameters

clubID `string` (required) page `string` (optional) pageSize `string` (optional) status `string` (optional) model `string` (optional) provider `string` (optional) source `string` (optional) `key` or `agent` keyHash `string` (optional) Filter to a single key/agent by its PH keyHash. q `string` (optional) Free-text search across request id, key/agent label, model, provider, end user. minutes `string` (optional) Sub-day window (e.g. Live=1440); overrides startDate/endDate. startTs `string` (optional) Epoch-seconds window start (click-to-zoom); overrides minutes/dates. endTs `string` (optional) Epoch-seconds window end (click-to-zoom); overrides minutes/dates.

Endpoint

GET /api/clubs/{clubID}/ai-credits/logs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/logs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Requests-over-time histogram for the Logs view. Same filters as the list route, but aggregated server-side into time buckets (success/failure counts) so the response is tiny regardless of log volume. Bucket size is chosen automatically for the span.

Parameters

clubID `string` (required) status `string` (optional) model `string` (optional) provider `string` (optional) source `string` (optional) keyHash `string` (optional) q `string` (optional) minutes `string` (optional) startDate `string` (optional) endDate `string` (optional) startTs `string` (optional) endTs `string` (optional)

Endpoint

GET /api/clubs/{clubID}/ai-credits/logs/histogram

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/logs/histogram \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Usage analytics buckets + per-model totals for a range (live from LiteLLM).

Parameters

clubID `string` (required) range `string` (optional) 24h | 7 | 30 | 90 | year | all (ignored if startDate/endDate given) startDate `string` (optional) endDate `string` (optional) groupBy `string` (optional) model (default) | key | source | provider | status — dimension for buckets + groups subgroupBy `string` (optional) optional second dimension nested under each group (Explore) keyHash `string` (optional) deep-dive filter — scope to a single key/agent model `string` (optional) deep-dive filter — scope to a single model provider `string` (optional) source `string` (optional) compare `string` (optional) set to "prev" to also return groupsPrev (immediately-preceding equal-length period)

Endpoint

GET /api/clubs/{clubID}/ai-credits/stats

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/stats \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Daily activity calendar over the rolling last year (GitHub-style ~53 weeks).

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/activity

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/activity \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Charge the stored SaaS-billing card to add prepaid Model Router credit.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/clubs/{clubID}/ai-credits/topup

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/topup \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Finalise a top-up after the applet completes 3DS authentication.

Parameters

clubID `string` (required)

Endpoint

POST /api/clubs/{clubID}/ai-credits/topup/confirm

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/topup/confirm \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Summary of the stored SaaS-billing card that top-ups / auto top-up will charge.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/payment-method

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/payment-method \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Ledger transactions for the facility, newest first. Optionally filtered by type (e.g. `types=topup,adjustment` for the money-movement history, or `types=charge-reconcile` with `from`/`to` for a month's usage deductions).

Parameters

clubID `string` (required) limit `integer` (optional) Max rows (default 50, max 200) types `string` (optional) Comma-separated transaction types (topup, charge-reconcile, refund, adjustment, trueup-shortfall) from `integer` (optional) Only transactions with createdAt >= from (unix seconds) to `integer` (optional) Only transactions with createdAt <= to (unix seconds)

Endpoint

GET /api/clubs/{clubID}/ai-credits/transactions

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/transactions \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Distinct `YYYY-MM` months (UTC, newest first) that contain at least one transaction of the requested types. Drives the data-driven year/month filter dropdowns so the UI only offers periods that actually have data.

Parameters

clubID `string` (required) types `string` (optional) Comma-separated transaction types (topup, charge-reconcile, refund, adjustment, trueup-shortfall)

Endpoint

GET /api/clubs/{clubID}/ai-credits/transactions/available-periods

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/transactions/available-periods \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Branded PDF payment receipt for a single Model Router transaction.

Parameters

clubID `string` (required) txId `string` (required)

Endpoint

GET /api/clubs/{clubID}/ai-credits/transactions/{txId}/receipt.pdf

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/transactions/{txId}/receipt.pdf \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bundle of branded PDF payment receipts for the selected top-up transactions, as a ZIP. Every id must be a top-up belonging to the facility — usage deductions and admin adjustments have no receipts and are rejected.

Parameters

clubID `string` (required) ids `string` (required) Comma-separated transaction ids (max 50)

Endpoint

GET /api/clubs/{clubID}/ai-credits/transactions/receipts.zip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/transactions/receipts.zip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Per-calendar-month (UTC) rollups of the facility's usage deductions, newest first. The current month is always included and flagged `isCurrentMonth` (month to date).

Parameters

clubID `string` (required) months `integer` (optional) Lookback window in months (default 12, max 24; ignored when `year` is set) year `integer` (optional) Scope the rollups to one UTC calendar year (e.g. 2026)

Endpoint

GET /api/clubs/{clubID}/ai-credits/usage-statements

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/usage-statements \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Branded monthly Usage Statement PDF — a summary of the month's usage deductions (daily subtotals + total). Explicitly not an invoice or receipt; no payment is collected by usage deductions.

Parameters

clubID `string` (required) month `string` (required) UTC calendar month, `YYYY-MM`

Endpoint

GET /api/clubs/{clubID}/ai-credits/usage-statements/{month}/statement.pdf

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/usage-statements/{month}/statement.pdf \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Raw usage-deduction line items for a month as CSV (transaction id, UTC timestamp, amount, balance after, lifetime spend snapshot) — the detail export that reconciles to the month's statement total.

Parameters

clubID `string` (required) month `string` (required) UTC calendar month, `YYYY-MM`

Endpoint

GET /api/clubs/{clubID}/ai-credits/usage-statements/{month}/detail.csv

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/usage-statements/{month}/detail.csv \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Usage/spend summary for the facility (live from LiteLLM + reconciled ledger).

Parameters

clubID `string` (required) tz `string` (optional) Viewer's IANA timezone — fallback for day/month spend windows when the facility has no timezone data.

Endpoint

GET /api/clubs/{clubID}/ai-credits/usage

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/ai-credits/usage \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Associates/Updates an AI Edge Processor device to a club

Parameters

body `string` (required) JSON Object for updating AI Edge Processor Device registration.

Endpoint

POST /api/ai-edge-processor/devices

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ai-edge-processor/devices \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Associates an AI Edge Processor device to a club. Resolves the device metadata-first (live heartbeat wins), backfills the registration row if the device never self-registered, and cleans up stale registration rows left behind by re-provisioned hardware.

Parameters

body `string` (required) JSON Object for updating AI Edge Processor Device registration.

Endpoint

POST /api/ai-edge-processor/devices/associate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ai-edge-processor/devices/associate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of bbox upload records in a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/bbox-timeline/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/bbox-timeline/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Camera database search index

Proxies the public docs camera-db search index (manufacturers, series, models, aliases) used by the Find my camera dialog when adding network cameras. Cached server-side for 12 hours.

Endpoint

GET /api/cctv/camera-db/search-index

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/camera-db/search-index \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Camera database manufacturer templates

Proxies a single manufacturer's RTSP URL templates and defaults from the public docs camera database. Slug is validated to prevent path traversal. Cached server-side for 12 hours.

Parameters

slug `string` (required) Manufacturer slug (e.g. hikvision)

Endpoint

GET /api/cctv/camera-db/manufacturers/{slug}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/camera-db/manufacturers/{slug} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of check-ins data for a facility

Parameters

club `string` (required) Internal ID of the club/facility that you wish to access. startDate `string` (optional) Start date in YYYY-MM-DD format endDate `string` (optional) End date in YYYY-MM-DD format timezone `string` (optional) Timezone for date interpretation (default Australia/Brisbane) nextToken `string` (optional) Pagination token for fetching next page

Endpoint

GET /api/cctv/check-ins/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/check-ins/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieve configuration for CCTV Frontend or UI

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/config/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/config/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get CCTV content delivery configuration

Returns the content domain used by CCTV clients to resolve media assets. The domain is driven by the CONTENT_DOMAIN environment variable, falling back to a stage-aware default (production serves /cctv, other stages serve /cctv-stg).

Endpoint

GET /api/cctv/content-config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/content-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Change configuration for CCTV Frontend or UI

Parameters

body `object` (required) Json Object of the new config block to add to the system.

Endpoint

PUT /api/cctv/config/:club/:section

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/cctv/config/:club/:section \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of Bucket Region availability for CCTV storage provider config

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/bucket-region/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/bucket-region/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Reset unidentified face collection

Resets the facility's unidentified CompreFace collection by deleting all subjects. DynamoDB person records, face detections, and OpenSearch timeline blocks are NOT affected. Only the underlying face recognition data is cleared. New shadow profiles will be created automatically as the system processes new camera detections.

Parameters

facilityId `string` (required)

Endpoint

DELETE /api/cctv/config/{facilityId}/unidentified-collection

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/cctv/config/{facilityId}/unidentified-collection \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get unidentified collection info

Returns the current subject count for the facility's unidentified CompreFace collection.

Parameters

facilityId `string` (required)

Endpoint

GET /api/cctv/config/{facilityId}/unidentified-collection-info

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/config/{facilityId}/unidentified-collection-info \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds a network camera (OEM/IP camera) via stream URL (RTSP, HTTP, HTTPS)

Parameters

body `string` (required) JSON Object for adding a network camera.

Endpoint

POST /api/cctv/devices/add-network-camera

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/add-network-camera \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bulk-add network cameras to an edge processor

Registers multiple RTSP/HTTP network cameras against one edge processor, then pushes FEED_CONFIG once so the device reloads configuration a single time.

Parameters

body `object` (required)

Endpoint

POST /api/cctv/devices/add-network-cameras

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/add-network-cameras \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Associates/Updates a device to a club

Parameters

body `string` (required) JSON Object for updating CCTV Device registration.

Endpoint

POST /api/cctv/devices

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Associates a device to a club

Parameters

body `string` (required) JSON Object for updating CCTV Device registration.

Endpoint

POST /api/cctv/devices/associate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/associate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Fires off a MQTT Request to a specific device UUID, And expects a response (via websocket) of the available capabilities of the camera.

Parameters

club `string` (required) Internal ID of the club that owns the device you are querying. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/cctv/devices/list-camera-capabilities/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/list-camera-capabilities/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List device registrations

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/devices/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/devices/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Removes a network camera by marking it as deleted and removing it from the Edge Processor FEED_CONFIG

Parameters

club `string` (required) Internal ID of the club that owns the device. balenaUUID `string` (required) UUID of the network camera to remove.

Endpoint

DELETE /api/cctv/devices/remove-network-camera/{club}/{balenaUUID}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/cctv/devices/remove-network-camera/{club}/{balenaUUID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Saves any/all configured camera capabilities and applies them to the device as a environment variable (via balena)

Parameters

club `string` (required) Internal ID of the club that owns the device you are querying. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/cctv/devices/save-camera-capabilities/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/save-camera-capabilities/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Saves a motion mask (if configured) for the camera and applies it to the device as a environment variable (via balena)

Parameters

club `string` (required) Internal ID of the club that owns the device you are querying. body `string` (required) Json Object of the camera mask.

Endpoint

POST /api/cctv/devices/save-camera-mask/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/save-camera-mask/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Sends a specific v4l2 command (such as brightness, or contrast) to the physical device

Parameters

club `string` (required) Internal ID of the club that owns the device you are querying. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/cctv/devices/set-camera-capability/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/set-camera-capability/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Test a network camera stream URL

Sends a test command to an edge processor to validate a camera stream URL using ffprobe

Request Body

Endpoint

POST /api/cctv/devices/test-stream

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/devices/test-stream \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Permanently deletes a single face detection record from the database. Used to remove mismatched or incorrect track entries from a person's activity log.

Parameters

club `string` (required) fdID `string` (required)

Endpoint

DELETE /api/cctv/face-detections/:club/:fdID

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/cctv/face-detections/:club/:fdID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of face detections data of a person

Parameters

club `string` (required) Internal ID of the club that you wish to access. personID `string` (required) ID of person within the face identification system

Endpoint

GET /api/cctv/face-detections/:club/:personID

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/face-detections/:club/:personID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns face detections that reference a given person crop image, queried via the personCropImage GSI.

Parameters

club `string` (required) Internal ID of the club that you wish to access. personCropImage `string` (required) Person crop image URL stored on the face detection record. limit `string` (optional) Maximum number of detections to return. nextToken `string` (optional) Pagination token from a previous response.

Endpoint

GET /api/cctv/face-detections-by-person-crop-image/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/face-detections-by-person-crop-image/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of face detections data of a club grouped from range relative to current time

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/face-detections/:club/timeline

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/face-detections/:club/timeline \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of face detections data of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/face-detections/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/face-detections/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search face detection timeline blocks in a facility using OpenSearch

Parameters

facilityId `string` (required) Internal ID of the facility to search in timezone `string` (required) IANA timezone for date conversion (e.g. Pacific/Auckland) startDate `string` (optional) Start date filter (YYYY-MM-DD), converted to startUnix using timezone endDate `string` (optional) End date filter (YYYY-MM-DD), converted to endUnix using timezone personId `string` (optional) Filter by a specific person ID query `string` (optional) Free-text search (e.g. person name) limit `string` (optional) Results per page (default 20, max 100) filters `string` (optional) JSON-encoded filters object (e.g., {"matchType":"identified"}) sortBy `string` (optional) Field to sort by (startUnix, endUnix, created). Default is endUnix. page `string` (optional) Page number for pagination (default 1) sortOrder `string` (optional) Sort direction (asc or desc). Default is desc.

Endpoint

GET /api/cctv/search/face-detections/timeline-blocks/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/search/face-detections/timeline-blocks/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of reports about the club facility

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/facility/:club/reports

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/facility/:club/reports \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Trigger on-demand heatmap generation. Invokes the same Starter logic that the scheduled cron uses, but allows targeting a specific facility, date/time, and set of periods. When called with no body, behaves identically to the cron — scans all eligible facilities and enqueues every device.

Request Body

Endpoint

POST /api/cctv/heatmaps/generate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/heatmaps/generate \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Resolve the location of a composed rolling-window heatmap PNG for a single device. Returns JSON metadata only — the PNG bytes live on the content domain, the frontend constructs the URL as: `${contentDomain}/cctv/${storageService}/${region}/${filePath}?s=${token}` Resolution order: 1. DynamoDB `composed#…` index hit → return immediately (~10 ms). 2. Wasabi HEAD on the deterministic cache key. On hit, write a backfill index row and return. 3. Stale-fallback: any composed record exists for this (device, range, hour) tuple, even from a different date. Returned immediately with `cache: 'HIT-STALE'` so the FE can paint *something*. A fresh compose is fired async. 4. Cold path: no record exists at all. Compose Lambda is queued via `InvocationType: 'Event'` and the endpoint returns `202 { cache: 'PENDING' }`. The FE polls until a record lands (typically 3-5 seconds). Today-handling: when `endDate` is the facility's local "today", the endpoint serves yesterday's PNG instead — today's slices are still being written by the Starter cron and a fresh composition would be incomplete. The response echoes the requested `endDate` and includes `endDateUsed` (= yesterday). `cache` enum: - `HIT` — served from DDB index for the requested date. - `HIT-FALLBACK` — today requested; served yesterday's index row. - `HIT-BACKFILL` — DDB miss but Wasabi had the PNG; row was just written. - `HIT-FALLBACK-BACKFILL` — backfill on the yesterday fallback. - `HIT-STALE` — no record for the requested date but a record exists from another date for this tuple; served immediately and a fresh compose is queued in the background. - `PENDING` — no record at all; compose has been queued. FE should poll. Response is `202 Accepted`, no `filePath`.

Parameters

facilityId `string` (required) deviceUUID `string` (required) Device to compose for. Compositions are per-device. hour `integer` (required) Hour of day 0–23 to compose across the lookback window. endDate `string` (optional) Last date in the window (YYYY-MM-DD). Defaults to today (facility tz). range `string` (optional) Lookback window. Must be one of the whitelisted ranges. nocache `integer` (optional) Set to `1` to bypass the DDB + HEAD cache layers and force a fresh compose.

Endpoint

GET /api/cctv/heatmaps/hourly/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/heatmaps/hourly/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Discover which hours of the day have `1h` slice records for a device over a rolling lookback window. The frontend uses this to populate the hour picker alongside a date + range picker before firing the composition endpoint (`/api/cctv/heatmaps/hourly/...`). Example: `GET /api/cctv/heatmaps/query-hourly/Birkdale?deviceUUID=abc123&endDate=2026-04-16&range=30d` Internally: one DynamoDB range query on `cctvheatmaps` (`sk BETWEEN 1h#{start}-00 AND 1h#{end}-23`), grouped by hour. Returns one entry per hour that has at least one slice, including a representative ref JPEG (taken from the most recent day in the window — ref is shared per-device-per-day).

Parameters

facilityId `string` (required) deviceUUID `string` (required) Device to query. Hourly slices are per-device. endDate `string` (optional) Last date in the window (YYYY-MM-DD). Defaults to today (facility tz). range `string` (optional) Lookback window. Must be one of the whitelisted ranges.

Endpoint

GET /api/cctv/heatmaps/query-hourly/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/heatmaps/query-hourly/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Query pre-generated heatmap records for a facility. **All records for a period type:** - `/api/cctv/heatmaps/Birkdale?periodType=1y` - `/api/cctv/heatmaps/Birkdale?deviceUUID=abc123&periodType=1d` **Date range — single period type:** - `/api/cctv/heatmaps/Birkdale?periodType=1d&from=2026-03-01&to=2026-03-31` - `/api/cctv/heatmaps/Birkdale?periodType=6h&from=2026-03-31&to=2026-03-31` **Date range — all applicable period types (omit periodType):** - `/api/cctv/heatmaps/Birkdale?from=2026-03-01&to=2026-03-31` Returns annual, semi-annual, quarterly, etc. down to 6h records that overlap the given range. **Point-in-time — all 9 period types for one device:** - `/api/cctv/heatmaps/Birkdale?deviceUUID=abc123&date=2026-03-15T14:30` Returns up to 9 records (1y, 6m, 3m, 2m, 1m, 1w, 1d, 12h, 6h).

Parameters

facilityId `string` (required) The facility identifier. deviceUUID `string` (optional) Query a specific device. When omitted, queries across all devices (GSI). periodType `string` (optional) Filter to a single period type. When omitted with from/to, queries all types. from `string` (optional) Start date (yyyy-mm-dd). Must be used with `to`. to `string` (optional) End date (yyyy-mm-dd). Must be used with `from`. date `string` (optional) Point-in-time lookup (yyyy-mm-dd or yyyy-mm-ddTHH:mm). Requires deviceUUID. Returns one record per period type.

Endpoint

GET /api/cctv/heatmaps/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/heatmaps/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the device livestream thumbnail

Parameters

club `string` (required) Internal ID of the club. deviceId `string` (required) Internal ID of the CCTV device.

Endpoint

GET /api/cctv/livestream/:club/thumbnail/:deviceId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/livestream/:club/thumbnail/:deviceId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Tell the CCTV system that you are going to watch a livestream

Parameters

club `string` (required) Internal ID of the club. deviceId `string` (required) Internal ID of the CCTV device.

Endpoint

POST /api/cctv/livestream/:club/iswatching/:deviceId

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/livestream/:club/iswatching/:deviceId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Approve an intersection match

Sets match status to confirmed and records the reviewer.

Parameters

club `string` (required) matchId `string` (required)

Endpoint

POST /api/cctv/matching/{club}/detail/{matchId}/approve

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/matching/{club}/detail/{matchId}/approve \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get a single intersection match with visit details

Returns the match record and its per-visit timing breakdown.

Parameters

club `string` (required) matchId `string` (required)

Endpoint

GET /api/cctv/matching/{club}/detail/{matchId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/matching/{club}/detail/{matchId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List intersection matches for a facility

Returns paginated matches filtered by status.

Parameters

club `string` (required) status `string` (optional) limit `integer` (optional) nextToken `string` (optional)

Endpoint

GET /api/cctv/matching/{club}/list

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/matching/{club}/list \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Reject an intersection match

Sets match status to rejected and records the reviewer.

Parameters

club `string` (required) matchId `string` (required)

Endpoint

POST /api/cctv/matching/{club}/detail/{matchId}/reject

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/matching/{club}/detail/{matchId}/reject \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get intersection matching summary counts

Returns match counts grouped by status for the facility.

Parameters

club `string` (required) Facility ID

Endpoint

GET /api/cctv/matching/{club}/summary

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/matching/{club}/summary \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Read the status of an in-flight "upsert identified person" operation (covers create and edit). Reads the row directly from the cctv-rekognition-api-owned `people-ops` table; no Lambda hop. Used by the CCTV frontend to poll progress after POST /api/cctv/people/{facility}/identified. Path is a sibling of `/cctv/people/...` (not nested under it) so the express router cannot mis-match `operationId` as `:personID` on `/cctv/people/:club/:personID`. See createAPIRouter glob order. Returns a `pending` placeholder while the upsertIdentifiedPerson Lambda hasn't yet written its first stage entry (cold-start window). The FE polling hook treats placeholder and pending identically, so this keeps the contract stable for callers.

Parameters

operationId `string` (required)

Endpoint

GET /api/cctv/people-operations/{operationId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people-operations/{operationId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds a face image (from an existing track detection) to the person's CompreFace recognition subject and stores a reference in the shadow photos table. Does NOT upload the image to Wasabi — it is already there as a face detection capture.

Parameters

club `string` (required) personID `string` (required) body `string` (required)

Endpoint

POST /api/cctv/people/:club/:personID/add-face

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/:club/:personID/add-face \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add shadow photos to a person record

Parameters

club `string` (required) Internal ID of the club that you wish to access. personID `string` (required) Record ID of the person body `string` (required) Json Object of the new config block to add to the system.

Endpoint

POST /api/cctv/people/:club/shadow-photos/:personID

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/:club/shadow-photos/:personID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Query shadow photos of a person

Parameters

club `string` (required) Internal ID of the club that you wish to access. personID `string` (required) Record ID of the person

Endpoint

GET /api/cctv/people/:club/shadow-photos/:personID

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people/:club/shadow-photos/:personID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Permanently removes a shadow photo record from CCTVShadowPhotosTable and removes the corresponding face from CompreFace (if faceId is stored).

Parameters

club `string` (required) personID `string` (required) id `string` (required) The shadow photo record ID (primary key)

Endpoint

DELETE /api/cctv/people/:club/shadow-photos/:personID/:id

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/cctv/people/:club/shadow-photos/:personID/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deletes references and associated rekognition records by a personID

Parameters

club `string` (required) Internal ID of the club that you wish to access. personID `string` (required) Unique ID of the CCTV person.

Endpoint

DELETE /api/cctv/people/:club/:personID

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/cctv/people/:club/:personID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a person record of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access. personID `string` (required) DB ID of the person.

Endpoint

GET /api/cctv/people/:club/:personID

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people/:club/:personID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get access zones matched to a person's membership profile

Resolves the person's member type, tags, and membership plans, then returns real access zones (origin=membership-plan, not absorbed) matched against include/exclude rules. The accessRestriction on each zone is trimmed to only the rules that matched the person. Child zone cameras are merged into parent zones.

Parameters

club `string` (required) Internal ID of the facility personID `string` (required) Person ID from the CCTV people table

Endpoint

GET /api/cctv/people/{club}/{personID}/allowed-zones

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people/{club}/{personID}/allowed-zones \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the current status of a merge job including per-source results. Poll this endpoint every 3-5 seconds while status is IN_PROGRESS.

Parameters

club `string` (required) mergeJobID `string` (required)

Endpoint

GET /api/cctv/people/:club/merge-status/:mergeJobID

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people/:club/merge-status/:mergeJobID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initiates a background merge of multiple unidentified person profiles into one survivor. Responds 202 immediately with a mergeJobID. Poll /merge-status/:mergeJobID for progress.

Parameters

club `string` (required) body `string` (required)

Endpoint

POST /api/cctv/people/:club/merge-unidentified

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/:club/merge-unidentified \
  -H "x-api-key: YOUR_API_KEY"

Add a face to the blacklist collection for a facility

Parameters

facilityId `string` (required) Internal ID of the facility

Request Body

Endpoint

POST /api/cctv/people/{facilityId}/blacklist

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/{facilityId}/blacklist \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Upsert an identified person in a facility — creates a new record or updates an existing one. Proxies to the upsertIdentifiedPerson Lambda, which writes the person record, uploads any supplied photo to Wasabi, and re-indexes the face in CompreFace. When `isNewRecord` is true (default) the Lambda runs the create branch (cctvPeople.save) and a `personID` is generated if not provided. When `isNewRecord` is false the Lambda runs the update branch (cctvPeople.update) — `personID` is required and must identify an existing record.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/cctv/people/{facilityId}/identified

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/{facilityId}/identified \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Update the set of optional partner fields synced into the CCTV people table for a facility.

Parameters

facilityId `string` (required) Internal ID of the facility

Request Body

Endpoint

PUT /api/cctv/people/{facilityId}/sync-fields

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/cctv/people/{facilityId}/sync-fields \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Returns a list of people data of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/people/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/people/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search people in a facility by face image. Invokes the cctv-rekognition-api imageFaceSearch Lambda with the uploaded base64 image and facility ID from the path. Returns ranked matches plus a DeepFace attribute summary.

Parameters

club `string` (required) Facility / club ID body `string` (required)

Endpoint

POST /api/cctv/people/{club}/search-by-face

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/{club}/search-by-face \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search people in a facility using OpenSearch

Parameters

facilityId `string` (required) Internal ID of the facility to search in query `string` (optional) Search term (e.g., name) page `string` (optional) Page number (default 1) limit `string` (optional) Results per page (default 20, max 100) filters `string` (optional) JSON-encoded filters object (e.g., {"membershipStatus":"active"}) sortBy `string` (optional) Field to sort by (created, lastName, firstName, membershipUpdatedOn). Default is created. sortOrder `string` (optional) Sort direction (asc or desc). Default is desc.

Endpoint

GET /api/cctv/search/people/:facilityId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/search/people/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates face detection items with a new personID and associates rekognition records

Parameters

club `string` (required) Internal ID of the club that you wish to access. body `string` (required) Json Object of the new config block to add to the system.

Endpoint

POST /api/cctv/people/:club/validate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/people/:club/validate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns an object of all availble filters for CCTV recordings data of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/recordings/filters/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/recordings/filters/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Stream recording.

Endpoint

GET /api/cctv/recordings/:club/:dir/:filename

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/recordings/:club/:dir/:filename \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update info about the recording.

Endpoint

PUT /api/cctv/recordings/:club/:dir/:filename

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/cctv/recordings/:club/:dir/:filename \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a summary of CCTV recordings data of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/recordings/:club/summary

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/recordings/:club/summary \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of CCTV recordings data of a club based on range relative to current time

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/recordings/:club/timeline

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/recordings/:club/timeline \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of CCTV recordings data of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/recordings/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/recordings/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Recordings are automatically deleted in a set period, use this function to retain recordings

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

POST /api/cctv/recordings/:club/:action

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/recordings/:club/:action \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search report snapshots for a facility within a date range

Parameters

facilityId `string` (required) Internal ID of the facility startDate `string` (required) Start date filter (YYYY-MM-DD) endDate `string` (required) End date filter (YYYY-MM-DD) deviceIds `string` (optional) Comma-separated list of camera/device IDs to filter by view `string` (optional) Alternate report view to compute (forwarded to the report Lambda)

Endpoint

GET /api/cctv/reports/search-report-snapshots/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/reports/search-report-snapshots/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Vector search over a facility's indexed CCTV media. Responds with a text/event-stream relayed from the searchAnything Lambda, so the client can render progress while a cold container loads the encoder. Events are `status`, then either `result` or `error`. Three ways to ask, two of them on this verb. Send `query` to search by free text. Send `seedIndex` + `seedKey` to search by example — "more like this" — using the vector of a row already in the index, which is how you find more of a result the user is looking at. To search by an image the user has, `POST` the bytes to this same path instead. Send words with a picture to narrow one with the other: **text gates, image ranks**. Candidates come from the seed, the words decide which of them survive, and visual similarity decides the order — so the results still look like the picture and the words throw out the ones that do not match. The two are never blended into one vector, which is why `queryKind` stays `similar` for a combined search; the presence of `query` on the result is what tells you a text gate was applied. Expect combined searches to return nothing fairly often, and treat that as a distinct outcome: `perIndex..textGated` counts candidates that matched the picture but not the words, so an empty page can be explained as "drop the words" rather than "try another picture". A seeded search with no words loads no encoder, so it never pays a cold start; adding words gives that up. Either way it searches every index by default: the crop, recording and timelapse vectors share one space, so a person crop can find matching footage. Seeded scores run far higher than text scores (image-to-image crosses no modality gap) and are filtered by a separate, still-uncalibrated floor — `result.queryKind` tells you which scale you are reading, and a score from one must never be compared with the other. Searches every index by default and returns one merged, score-sorted list; each hit carries `index` and `kind` so the caller can tell an image hit from a video hit (the latter adds `offsetMs`). Indexes with no table for the facility are reported in `skipped` rather than failing. Hits below each index's calibrated relevance floor are dropped, so a query with no real match returns an empty list instead of confident nonsense; `perIndex` reports what each index contributed and why. Results can be narrowed by capture time and by camera. Prefer `cameraId` over `camera`: it is the camera's balenaUUID, which is the one value every index stores identically, so a single filter narrows all of them. A filter an index cannot answer is reported under `perIndex..filtersIgnored` and that index is searched unnarrowed, rather than dropped from the search. Recording hits are **one per clip, not one per matched frame**: frames are sampled every 2 s, so a subject who lingers matches ten near identical frames of the same recording. Each clip returns its best frame, plus `matchCount` and `offsetsMs` listing every moment that matched inside it, which are usable directly as seek points. Person crops are never collapsed, since two crops of one person are two distinct sightings.

Parameters

facilityId `string` (required) Internal ID of the facility to search in query `string` (optional) Free-text description of what to look for. Required unless warm=1 or a seed is sent. Combined with a seed it stops being the thing ranked and becomes a filter over the seed's candidates, dropping those whose text score falls below the index's relevance floor. seedIndex `string` (optional) Search by example instead of by text: the index the seed row lives in (person-crops, recording-frames, timelapse-frames). This is the `index` of the hit the user clicked. Must be sent with seedKey. seedKey `string` (optional) The seed row's `key`, taken verbatim from the hit. The seed is excluded from its own results — for a recording that means the whole clip, since its other frames are 2s apart and near-identical. seedFrameId `string` (optional) Required when seedIndex is recording-frames: that index stores one row per sampled frame and they all share the clip's key, so the key alone names a clip rather than a moment. Send the hit's `frameId`. Older rows have none — send seedOffsetMs instead. seedOffsetMs `string` (optional) Fallback frame identifier for recording-frames seeds whose row predates `frame_id`. Send the hit's `offsetMs`. Ignored when seedFrameId is supplied. warm `string` (optional) Prime a Lambda container without running a search. Fire this on page load. warmTarget `string` (optional) Which encoder `warm` loads: `text` (default), `image`, or `both`. The vision tower is 355 MB against the text tower's 283 MB, so priming it is opt-in — ask for `image` only once the user has actually staged a picture, not on page load. index `string` (optional) Comma-separated datasets to search: person-crops, recording-frames, timelapse-frames. Results are merged into one score-sorted list. All three are searched by default; pass an explicit list to narrow it. timelapse-frames covers cameras that record nothing and only produce a frame a minute, and its relevance floor is not yet calibrated. model `string` (optional) Encoder to query with. Must match the encoder the dataset was indexed by. limit `string` (optional) Results to return per index (default 50, max 100) — not a total, so searching all three indexes can return up to three times this. For recordings it counts clips rather than matched frames. from `string` (optional) Only match media captured at or after this time, in milliseconds since the epoch. Note this is capture time, not upload time. to `string` (optional) Only match media captured before this time (exclusive), in milliseconds since the epoch. cameraId `string` (optional) Comma-separated camera balenaUUIDs to narrow to — the `balenaUUID` field of each entry returned by /api/cctv/recordings/filters/:club. The preferred camera filter: every index stores this same value, so one filter narrows all of them. Note that only crops whose face-detection join resolved carry it (~1% today), so narrowing crops by camera will return few or none until the crop backfill runs; recordings are fully populated and filter exactly. camera `string` (optional) Comma-separated camera names to narrow to. Effectively recordings-only: person-crops stores an empty camera name on every row, so any value here excludes all crops. Prefer cameraId. cameraGroup `string` (optional) Comma-separated camera groups to narrow to. Populated on all recordings but only ~1% of crops, same cause as cameraId. minScore `string` (optional) Override the per-index cosine floor that filters out noise. Omit in production; each index carries a calibrated default (and a separate, uncalibrated one for seeded searches). Pass 0 to see unfiltered nearest neighbours when debugging relevance.

Endpoint

GET /api/cctv/search/anything/:facilityId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/search/anything/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search by an image the user has, rather than by words or by a result already on screen. Identical to the GET in every other respect — same query parameters, same event stream, same result shape — so this documents only what differs. Send the **original file bytes** as the request body with an `image/*` Content-Type. Do not resize, crop or re-encode it in the browser first: the server matches a very specific resize (a squash to 256x256 with an antialiased bilinear kernel) that the indexed vectors were built with, and canvas scaling uses a different one. Measured, that substitution lands roughly 0.93 cosine away from the right answer, which is further apart than two genuinely different images — so the results come back ranked plausibly and wrongly, with no error. Limited to 4 MB, which is a transport constraint rather than a quality one: the bytes travel inside the Lambda invoke payload, which caps at 6 MB, and base64 inflates them by a third. Results are scored image-to-image, so `queryKind` is `image` and the scores are on the same much higher scale as a seeded search — never comparable with text scores. Expect them to run slightly *below* an equivalent seeded search: a seed's vector was written by the device itself, whereas an upload is re-encoded here by a different engine, which lands it a few hundredths away from where the device would have put it. Measured, the results are of equal quality despite that; they are simply not the identical set. Adding `query` gates the results by those words, exactly as it does for a seed. Sending a seed *and* an image is rejected: both are the thing being ranked, so the pair has no meaning. This is the most expensive request the endpoint serves. An uploaded image loads the vision tower, and adding words loads the text tower too — both on a cold container. `warm=1&warmTarget=image` once the user stages a picture takes that off the critical path.

Parameters

facilityId `string` (required) Internal ID of the facility to search in body `string` (required) Raw image bytes, unmodified, 4 MB maximum query `string` (optional) Optional words to narrow the image results by, dropping matches whose text score falls below the index's relevance floor.

Endpoint

POST /api/cctv/search/anything/:facilityId

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/search/anything/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns storage details and other metric data for club CCTV

Endpoint

GET /api/cctv/storage-details/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/storage-details/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of timelapse upload records of a club

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/timelapse/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/timelapse/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List user actions performed on the recordings in CCTV Frontend or UI

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/cctv/ui/actions/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/ui/actions/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Record a user action performed on the recordings in CCTV Frontend or UI

Parameters

body `string` (required) Json Object of the new config block to add to the system.

Endpoint

POST /api/cctv/ui/actions/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/ui/actions/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get user token for CCTV Frontend or UI

Parameters

club `string` (required) Club ID

Endpoint

GET /api/cctv/ui/token/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/ui/token/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generate token for temporary or guest access

Parameters

club `string` (required) The unique identifier for the club. body `string` (required) JSON Object of the token details to issue.

Endpoint

POST /api/cctv/token/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/cctv/token/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{
  "accessID": "2cdfde23-5008-4ae7-b830-374abe8d509f"
}

Returns a list of records of tokens for temporary or guest access

Parameters

club `string` (required) The unique identifier for the club.

Endpoint

GET /api/cctv/token/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/cctv/token/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get access token via access ID

Parameters

accessID `string` (required) ID of the token record in the DB.

Endpoint

POST /guest/cctv/token/:accessID

Example Request

curl -X POST https://portal.hub.gymsystems.co/guest/cctv/token/:accessID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a facility access hours

Parameters

facilityId `string` (required) body `object` (required) Json Object of the new access hours.

Endpoint

DELETE /api/ai/computer-vision/access-hours/:facilityId

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/ai/computer-vision/access-hours/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of facility access hours

Parameters

facilityId `string` (required)

Endpoint

GET /api/ai/computer-vision/access-hours/:facilityId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ai/computer-vision/access-hours/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates or creates a facility access hours

Parameters

facilityId `string` (required) body `object` (required) Json Object of the new access hours.

Endpoint

POST /api/ai/computer-vision/access-hours/:facilityId

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ai/computer-vision/access-hours/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a facility access zone

Parameters

facilityId `string` (required) body `object` (required) Json Object of the new access zone.

Endpoint

DELETE /api/ai/computer-vision/access-zones/:facilityId

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/ai/computer-vision/access-zones/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of facility access zones

Parameters

facilityId `string` (required)

Endpoint

GET /api/ai/computer-vision/access-zones/:facilityId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ai/computer-vision/access-zones/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates or creates a facility access zone

Parameters

facilityId `string` (required) body `object` (required) Json Object of the new access zone.

Endpoint

POST /api/ai/computer-vision/access-zones/:facilityId

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ai/computer-vision/access-zones/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the union of all admin module IDs across brands and facilities for an organisation, populated as module objects.

Parameters

organisationId `string` (required) Organisation ID

Endpoint

GET /api/organisations/{organisationId}/admin-modules

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/organisations/{organisationId}/admin-modules \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List org-level HQ canned response templates used as global suggestions in the customer review reply dialog.

Parameters

organisationId `string` (required)

Endpoint

GET /api/organisations/{organisationId}/hq-canned-responses

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/organisations/{organisationId}/hq-canned-responses \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Replace the full list of HQ canned response templates for the organisation.

Parameters

organisationId `string` (required)

Endpoint

PUT /api/organisations/{organisationId}/hq-canned-responses

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/organisations/{organisationId}/hq-canned-responses \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of all organisations

Parameters

includeBrands `string` (optional) Include brands associated with the organisation includeFacilities `string` (optional) Include facilities associated with the organisation includeRegions `string` (optional) Include regions associated with the organisation

Endpoint

GET /api/organisations

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/organisations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert an organisation

Parameters

organisationId `string` (optional) The ID of the organisation to update logo `string` (optional) An s3 object including the key and bucket name or an object containing the url of the logo name `string` (required) The name of the organisation modules `string` (optional) A list of the modules the organisation has access to disabledModules `string` (optional) Deny list of catalog modules flagged defaultOn that this organisation has explicitly opted out of websiteDomain `string` (optional) The domain name of the organisation primaryContactName `string` (optional) The name of the primary contact for the organisation primaryContactPhone `string` (optional) The phone number of the primary contact for the organisation registeredAddress `string` (optional) The registered address of the organisation organisationType `string` (optional) The type of organisation organisationTypeOther `string` (optional) The type of organisation if other platformStack `string` (optional) The account type / platform stack for the organisation. Controls which modules are available: 'business' (Business Suite + Technology Stack, all modules, default) or 'technology' (Technology Stack only, limited subset).

Endpoint

PUT /api/organisations

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/organisations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

A simple AI helper to analise the contents of a support ticket and create suggestions based on available topics as well as suggested algolia search topics...

Parameters

messageBody `string` (required) Body of the message to send topicData `string` (required) Json object/array of the topicData returned from osTicket (ticketing/support system) facilityId `string` (optional) The internal ID of the club needed to determine the correct Algolia index to search against.

Endpoint

PUT /api/ai/helpers/analyse-support-ticket

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ai/helpers/analyse-support-ticket \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

A simple image generation api

Parameters

type `string` (required) Type of image to generate name `string` (required) Image name maxSize `string` (optional) Optional maximum response size, e.g. 200KB, 1MB or a plain byte count. The image is downscaled/compressed to fit.

Endpoint

PUT /api/ai/images/:type/:name

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ai/images/:type/:name \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Simple LLM query

Lightweight endpoint for simple, stateless LLM queries. Uses a cheap, non-reasoning model (gpt-4o-mini) with strict token limits. No conversation history, no tools, no streaming — just prompt in, text out.

Request Body

Endpoint

POST /api/ai/llm/query

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ai/llm/query \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

A simple AI helper to analise the contents of a support ticket and create suggestions based on available topics as well as suggested algolia search topics...

Parameters

messageBody `string` (required) Body of the message to send topicData `string` (required) Json object/array of the topicData returned from osTicket (ticketing/support system)

Endpoint

PUT /internal/ai/helpers/analyse-support-ticket

Example Request

curl -X PUT https://portal.hub.gymsystems.co/internal/ai/helpers/analyse-support-ticket \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the Algolia configuration including index name, app ID, and API key.

Parameters

facilityId `string` (required)

Endpoint

GET /api/facilities/{facilityId}/algolia/config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/algolia/config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initializes the Algolia marketing print index

Parameters

organisationId `string` (required)

Endpoint

PUT /api/algolia/index

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/algolia/index \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search for marketing print materials

Request Body

Endpoint

POST /algolia/search-marketing-print

Example Request

curl -X POST https://portal.hub.gymsystems.co/algolia/search-marketing-print \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Search for marketing print materials

Parameters

club `string` (optional) Club ID searchTerms `string` (optional) Search terms algoliaArgs `object` (optional) Additional Algolia search arguments

Endpoint

GET /algolia/search-marketing-print

Example Request

curl -X GET https://portal.hub.gymsystems.co/algolia/search-marketing-print \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bulk update marketing print objects for a specific club

Endpoint

POST /algolia/bulk-update-marketing-print

Example Request

curl -X POST https://portal.hub.gymsystems.co/algolia/bulk-update-marketing-print \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Fetches marketing print assets from Algolia.

Parameters

organisationId `string` (required) search `string` (optional) limit `string` (optional) brand `string` (optional) tag `string` (optional)

Endpoint

GET /api/algolia/marketing/assets

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/algolia/marketing/assets \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initializes the Algolia marketing print index with the facility's configuration.

Parameters

organisationId `string` (required)

Endpoint

POST /api/algolia/marketing/assets

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/algolia/marketing/assets \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Performs a search against a specified Algolia index based on search terms, club, and/or locale. The search can be further customized using additional Algolia arguments.

Parameters

searchTerms `string` (required) The terms to search for in the Algolia index. club `string` (optional) Internal ID of the club that is making the request. If specified, the search will be filtered based on the region associated with the club. locale `string` (optional) The locale to use for determining the region if a club is not specified. Derived from navigator.languages. algoliaArgs `string` (optional) Additional/custom arguments to pass through to the Algolia search request.

Endpoint

POST /api/algolia/search-wiki

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/algolia/search-wiki \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Removes an announcement from the system.

Parameters

body `string` (required) Json Object of the design ID to remove.

Endpoint

DELETE /api/announcements/delete

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/announcements/delete \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all announcements

Endpoint

GET /api/announcements/list

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/announcements/list \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Saves/Updates one or more announcements in the system.

Parameters

body `object` (required) Json object containing the announcement to add/update/save in the system...

Endpoint

PUT /api/announcements/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/announcements/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Uploads an image for the announcements WYSIWYG editor, and returns response suitable for Froala Image Upload: [https://froala.com/wysiwyg-editor/docs/concepts/image/upload/](https://froala.com/wysiwyg-editor/docs/concepts/image/upload/)

Parameters

file `string` (optional) Name of the file/asset to be uploaded.

Endpoint

POST /api/announcements/upload-image

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/announcements/upload-image \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Uploads an asset to a PUBLIC S3 BUCKET (via the Upload API) which then will post-process/optimise the file, generate thumbnails etc. *Note, Assets will be publicly available*

Parameters

file `string` (optional) Name of the file/asset to be uploaded.

Endpoint

POST /api/asset-upload

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/asset-upload \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the status of upload by the given uuid of the upload record

Parameters

uuid `string` (required) UUID of the upload record

Endpoint

GET /api/asset-upload/:uuid

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/asset-upload/:uuid \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Send a command to club Sonos

Parameters

body `object` (required) Json Object of the command and input to send to Sonos.

Endpoint

PUT /api/audio-control/command/:club

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/audio-control/command/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieve configuration for Audio Control Frontend

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/audio-control/config/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/audio-control/config/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Change configuration for Audio Control Frontend

Parameters

body `object` (required) Json Object of the new config block to add to the system.

Endpoint

PUT /api/audio-control/config/:club/:section

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/audio-control/config/:club/:section \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieves brand settings for a specific region

Parameters

brandId `string` (optional) The ID of the brand regionCode `string` (optional) The ISO code of the region to retrieve settings for

Endpoint

GET /api/brands/{brandId}/regions/{regionCode}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId}/regions/{regionCode} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates multiple brand settings for a specific region

Parameters

brandId `string` (optional) The ID of the brand to update regionCode `string` (optional) The ISO code of the region to update settings for acceptFreeTrialBookingsVisibility `string` (optional) customTrackingCodeVisibility `string` (optional) displayDataSources `string` (optional) displayDefaultDataSource `string` (optional) displayDefaultUI `string` (optional) displayUIOptions `string` (optional) defaultAboutBusiness `string` (optional) defaultAboutBusinessFacebook `string` (optional) facilityCoverImage `string` (optional) digitalProfileSettingsVisibility `string` (optional) facilityHoursVisibility `string` (optional) facilityLocationVisibility `string` (optional) facilityPaymentMethods `string` (optional) facilityPrimaryLogo `string` (optional) facilityStatusVisibility `string` (optional) landingPagesVisibility `string` (optional) lineChatIntegrationVisibility `string` (optional) whatsAppIntegrationVisibility `string` (optional) defaultWhatsAppMessage `string` (optional) socialUrlsVisibility `string` (optional) yextApiKey `string` (optional) API key used by the Yext integration for this brand-region. Only consulted when `directorySyncMode` is `yext`. directorySyncMode `string` (optional) Which sync backend should run for facilities under this brand-region. Defaults to `yext` when missing for back-compat with brands that pre-date the Directory Publishers rollout. websiteUrl `string` (optional) androidAppUrl `string` (optional) iosAppUrl `string` (optional) featuredMessageDescription `string` (optional) yextCategoryIds `string` (optional) Legacy storage key — these are actually Google Business Profile category IDs (e.g. gcid:gym). The "yext" prefix predates the Yext deprecation; kept for back-compat with existing DB rows. customInputFields `string` (optional) customInputFieldsToRemove `string` (optional)

Endpoint

PUT /api/brands/{brandId}/regions/{regionCode}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/brands/{brandId}/regions/{regionCode} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieves brand settings for a specific facility

Parameters

facilityId `string` (optional) The ID of the facility to retrieve brand settings for

Endpoint

GET /api/facilities/{facilityId}/brand-settings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/brand-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a new brand

Parameters

name `string` (required) The name of the brand organisationId `string` (required) The ID of the organisation the brand belongs to redirectDashboard `string` (optional) The URL to redirect to after logging in instead of the default dashboard

Endpoint

POST /api/brands

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/brands \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all brands

Endpoint

GET /api/brands

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the brand object

Parameters

brandId `string` (required) The ID of the brand to retrieve includeOrganisation `boolean` (optional) Whether to include the organisation data in the response

Endpoint

GET /api/brands/{brandId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a brand by ID

Parameters

brandId `string` (optional) The ID of the brand to update name `string` (required) The name of the brand brandOrganisationId `string` (optional) The ID of the organisation the brand belongs to redirectDashboard `string` (optional) The URL to redirect to after logging in instead of the default dashboard yextApiKey `string` (optional) The API key used to access the Yext API for this brand adminModules `string` (optional) Admin-only module IDs (global admins only) customMenuLayout `object` (optional) Per-brand side-menu layout tree (sections / groups / items with refs to system modules or custom URLs). Only settable by a global admin or an organisation admin for this brand's organisation.

Endpoint

PUT /api/brands/{brandId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/brands/{brandId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List facilities for a brand

Returns a lightweight list of facilities (id, name, region ISO code) belonging to the brand. Used to populate facility targeting selectors in brand config.

Parameters

brandId `string` (required) The ID of the brand to list facilities for

Endpoint

GET /api/brands/{brandId}/facilities

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId}/facilities \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all brands associated with the organisation of the club.

Endpoint

GET /api/clubs/{club}/brands

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/brands \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all calendar types

Endpoint

GET /api/programs/calendars/calendar-types

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/programs/calendars/calendar-types \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a dashboard banner

Soft-deletes a dashboard banner belonging to the brand.

Parameters

brandId `string` (required) The ID of the brand the banner belongs to bannerId `string` (required) The ID of the banner to delete

Endpoint

DELETE /api/brands/{brandId}/dashboard-banners/{bannerId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/brands/{brandId}/dashboard-banners/{bannerId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List dashboard banners for a brand

Returns all (non-deleted) dashboard banners configured for the brand, for admin management.

Parameters

brandId `string` (required) The ID of the brand to list banners for

Endpoint

GET /api/brands/{brandId}/dashboard-banners

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId}/dashboard-banners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update a dashboard banner

Creates a new dashboard banner for the brand, or updates an existing one when `bannerId` is supplied in the body. Banners can be scheduled (unix-second start/end, null = unbounded) and targeted at the whole brand, specific regions (ISO codes) or specific facilities.

Parameters

brandId `string` (required) The ID of the brand the banner belongs to

Request Body

Endpoint

PUT /api/brands/{brandId}/dashboard-banners

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/brands/{brandId}/dashboard-banners \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get active dashboard banners for a facility

Resolves the dashboard banners that should currently be shown for a facility, based on the facility's brand, region (ISO country code) and each banner's enabled flag, schedule window and targeting. Consumed by the dashboard UIs.

Parameters

facilityId `string` (required) The ID of the facility to resolve banners for

Endpoint

GET /api/facilities/{facilityId}/dashboard-banners

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/dashboard-banners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the KYC asset for a club.

Parameters

clubId `string` (required) The ID of the club. key `string` (required) The key of the KYC asset.

Endpoint

GET /api/clubs/{clubId}/kyc-assets/{key}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubId}/kyc-assets/{key} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the club KYC information.

Endpoint

GET /api/clubs/{clubId}/kyc

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubId}/kyc \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the club KYC information.

Parameters

clubId `string` (required) The ID of the club to update. body `object` (required)

Endpoint

PUT /api/clubs/{clubId}/kyc

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubId}/kyc \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Uploads a KYC asset for a club.

Parameters

clubId `string` (required) The ID of the club. file `string` (required) The file to upload.

Endpoint

POST /api/clubs/{clubId}/kyc-assets

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubId}/kyc-assets \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the club preference settings.

Endpoint

GET /api/club/preferences/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/preferences/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates or updates club preferences entry.

Request Body

Endpoint

POST /api/club/preferences/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/club/preferences/:club \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Returns list of members with agreement.

Endpoint

GET /api/clubpass/user/email/exist/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubpass/user/email/exist/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of members with agreement.

Endpoint

GET /api/clubpass/user/phone/exist/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubpass/user/phone/exist/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of users that belong to the specified club

Parameters

club `string` (required) Internal ID of the club that you wish to access

Endpoint

GET /api/clubs/{club}/members

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/members \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns if club is open on given date.

Parameters

club `string` (required) Internal ID of the club that you wish to access. date `string` (required) Date to check for in unix format

Endpoint

GET /api/club-busy-hours/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club-busy-hours/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all metadata for the Club that is displayed on the UBX websites.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/clubs/clubpage/clubdata/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/clubpage/clubdata/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a club's Meta Data with new data provided from the front-end. Fields absent from the request body are preserved (no SET, no REMOVE). Fields sent as `null` or empty string are cleared. Pass `updateAll: false` to use the dedicated partial-merge path; either way, callers never need to send fields they don't own.

Parameters

club `string` (required) Internal ID of the club that you wish to access. body `string` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/clubs/clubpage/updateclub/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/clubpage/updateclub/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

add new custom tracking record

Parameters

club `string` (required) id of the club body `string` (required) Array of custom tracking items.

Endpoint

POST /api/clubs/{club}/customtracking

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{club}/customtracking \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns custom tracking for specific club

Endpoint

GET /api/clubs/customtracking/:clubID

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/customtracking/:clubID \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update custom tracking entries

Parameters

club `string` (required) id of the club body `string` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/clubs/{club}/customtracking/update

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{club}/customtracking/update \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the default shop front image for a club.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/clubs/{club}/default-shop-front

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/default-shop-front \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List doors available in the facility

Parameters

body `object` (required) JSON Object of club data that you wish to update.

Endpoint

POST /api/clubs/integrations/doors/:facilityId

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/integrations/doors/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Unlock a specific door in the facility

Parameters

body `object` (required) JSON Object of club data that you wish to update.

Endpoint

POST /api/clubs/integrations/doors/unlock

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/integrations/doors/unlock \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all integrations and the configuration details for the specified club.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/clubs/integrations/list/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/integrations/list/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a club's Meta Data with new data provided from the front-end.

Parameters

club `string` (required) Internal ID of the club that you wish to access. body `object` (required) Json Object of club data that you wish to update.

Endpoint

POST /api/clubs/integrations/update/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/integrations/update/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns boolean if club is a European country or not

Parameters

club `string` (required) Internal ID of the club that you wish to access. date `string` (required) Date to check for in unix format

Endpoint

GET /api/clubs/is-eu/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/is-eu/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns high level list of all clubs in our database.

Endpoint

GET /api/clubs/listclubs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/listclubs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns if club is open on given date.

Parameters

club `string` (required) Internal ID of the club that you wish to access. date `string` (required) Date to check for in unix format

Endpoint

GET /api/clubs/{club}/open-on/{date}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/open-on/{date} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the club reviews from dynamo db.

Parameters

club `string` (required) Club ID

Endpoint

GET /api/clubs/{club}/reviews

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/reviews \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the club reviews settings from dynamo db.

Parameters

facilityId `string` (required) facility ID

Endpoint

GET /api/clubs/{club}/reviews-settings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/reviews-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the club reviews settings on dynamo db.

Parameters

club `string` (required) Club ID

Endpoint

PUT /api/clubs/{club}/reviews-settings

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Re-enable review settings auto pyblish.

Parameters

club `string` (required) Club ID

Endpoint

PUT /api/clubs/{club}/reviews/publish-recent-reviews

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews/publish-recent-reviews \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Publishes a review

Parameters

club `string` (required) Internal ID of the club that you wish to access. review `string` (required) Internal ID of the review that you wish to publish.

Endpoint

PUT /api/clubs/{club}/reviews/{review}/publish

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews/{review}/publish \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Re-enable review settings auto pyblish.

Parameters

club `string` (required) Club ID

Endpoint

PUT /api/clubs/{club}/reviews-settings/re-enable-auto-publish

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews-settings/re-enable-auto-publish \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Post a response to a review back out through its originating publisher (Google etc.).

Parameters

club `string` (required) Facility ID reviewId `string` (required) PH review ID (looked up against the club-social-reviews table) body `string` (required)

Endpoint

POST /api/clubs/{club}/reviews/{reviewId}/respond

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{club}/reviews/{reviewId}/respond \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Un-publishes a review

Parameters

club `string` (required) Internal ID of the club that you wish to access. review `string` (required) Internal ID of the review that you wish to un-publish.

Endpoint

PUT /api/clubs/{club}/reviews/{review}/un-publish

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews/{review}/un-publish \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of owners that belong to the specified club from the PH db

Parameters

clubID `string` (required) Internal ID of the club that you wish to access

Endpoint

GET /api/clubs/{clubID}/owners

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/owners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all membership plans for the facility.

Parameters

facilityId `string` (required) Internal ID of the facility

Endpoint

GET /api/facilities/membership-plans/:facilityId

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/membership-plans/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a membership plan record.

Parameters

facilityId `string` (required) Internal ID of the facility body `object` (required) JSON Object of membership plan data that you wish to update.

Endpoint

PUT /api/facilities/membership-plans/:facilityId

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/facilities/membership-plans/:facilityId \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Re-enable review settings auto pyblish.

Parameters

club `string` (required) Club ID

Endpoint

PUT /api/clubs/{club}/reviews/publish-recent-reviews

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews/publish-recent-reviews \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Re-enable review settings auto pyblish.

Parameters

club `string` (required) Club ID

Endpoint

PUT /api/clubs/{club}/reviews-settings/re-enable-auto-publish

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{club}/reviews-settings/re-enable-auto-publish \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all available currencies

Endpoint

GET /api/currencies

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/currencies \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the geographical location using IP address.

Parameters

ip `string` (required) IP address to look up

Endpoint

GET /api/geo/ip-location/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/geo/ip-location/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the geographical location of the current user based on their IP.

Endpoint

GET /api/geo/ip-current

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/geo/ip-current \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the requesting client's public IP address only (no geolocation lookup, no third-party API call). Used by the AI Agent applet to compare the browser's public IP with a device's beaconed WAN IP for same-network detection.

Endpoint

GET /api/geo/client-ip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/geo/client-ip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Phone parser.

Parameters

body `string` (required) Json Object of the number you wish to parse.

Endpoint

POST /api/phone/parser

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/phone/parser \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns master clock device

Parameters

club_id `string` (required) Internal ID of the club that you wish to add the device under.

Endpoint

GET /api/clubs/{club_id}/smart-club/health-check/master-clock

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club_id}/smart-club/health-check/master-clock \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns master sonos device

Parameters

club_id `string` (required) Internal ID of the club that you wish to add the device under.

Endpoint

GET /api/clubs/{club_id}/smart-club/health-check/sonos-mqtt

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club_id}/smart-club/health-check/sonos-mqtt \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

get low battery duress notifications for a given club.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/clubs/{club}/smart-club/health-check/low-battery-duress

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/smart-club/health-check/low-battery-duress \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns network analysis data

Parameters

club_id `string` (required) Internal ID of the club that you wish to add the device under.

Endpoint

GET /api/clubs/{club_id}/smart-club/health-check/network-analysis

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club_id}/smart-club/health-check/network-analysis \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

send low battery duress notifications for a given club.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/clubs/{club}/smart-club/health-check/send-low-battery-duress-notifs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club}/smart-club/health-check/send-low-battery-duress-notifs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns device speed test data for each device type

Parameters

club_id `string` (required) Internal ID of the club that you wish to add the device under.

Endpoint

GET /api/clubs/{club_id}/smart-club/health-check/speed-test

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{club_id}/smart-club/health-check/speed-test \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List publisher configs for an organisation.

Parameters

organisationId `string` (required)

Endpoint

GET /api/admin/directory-publishers/config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/directory-publishers/config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable/disable a publisher at org level, or store OAuth credentials.

Endpoint

PUT /api/admin/directory-publishers/config

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/directory-publishers/config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Connect Apple Business Connect for an organisation by storing the org's ABC Company ID. The org must delegate access to UBX's Partner ID in the Apple Business Connect portal before sync can succeed.

Parameters

organisationId `string` (required)

Request Body

Endpoint

POST /api/admin/directory-publishers/{organisationId}/apple/connect

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/directory-publishers/{organisationId}/apple/connect \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Connect Facebook Pages for an organisation by accepting a Meta App's App ID, App Secret, and a long-lived user access token. Verifies scopes via /debug_token, exchanges the supplied token for a fresh 60-day token, fetches the user identity, and persists the credentials onto the directorypublisherconfig record.

Parameters

organisationId `string` (required)

Request Body

Endpoint

POST /api/admin/directory-publishers/{organisationId}/facebook/connect

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/directory-publishers/{organisationId}/facebook/connect \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List candidate listings owned by the org's connected publisher account. Used by the Bind dialog to let admins attach an existing publisher entity to a PH facility instead of creating a duplicate.

Parameters

organisationId `string` (required) publisherId `string` (required)

Endpoint

GET /api/admin/directory-publishers/{organisationId}/{publisherId}/listings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/directory-publishers/{organisationId}/{publisherId}/listings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generate OAuth URL for a publisher connection.

Parameters

publisherId `string` (required) organisationId `string` (required)

Endpoint

GET /api/admin/directory-publishers/auth-url

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/directory-publishers/auth-url \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Handle OAuth callback from a publisher.

Parameters

code `string` (required) state `string` (required)

Endpoint

GET /api/admin/directory-publishers/callback

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/directory-publishers/callback \
  -H "x-api-key: YOUR_API_KEY"

Disconnect a publisher from an organisation.

Parameters

organisationId `string` (required) publisherId `string` (required)

Endpoint

DELETE /api/admin/directory-publishers/{organisationId}/{publisherId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/directory-publishers/{organisationId}/{publisherId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Rotate the Facebook long-lived user token for an already-connected org without going through full disconnect/reconnect. Reuses the stored App ID + App Secret, verifies the pasted token has every required scope, exchanges it for a fresh 60-day token, and writes only the token-scoped fields onto authCredentials. connectedAt / connectedBy / enabled / createdAt are intentionally untouched so the publisher card "Connected by ..." identity stays put. 404s if the org has no existing Facebook config — admins must do a full /facebook/connect first to provide App ID + Secret.

Parameters

organisationId `string` (required)

Request Body

Endpoint

POST /api/admin/directory-publishers/{organisationId}/facebook/refresh-token

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/directory-publishers/{organisationId}/facebook/refresh-token \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Returns the publishers enabled for the facility's organisation, with their connection status.

Parameters

facilityId `string` (required) organisationId `string` (required)

Endpoint

GET /api/facilities/{facilityId}/directory-publishers/resolved

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/directory-publishers/resolved \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get listing insights for a facility. Returns aggregated daily totals across publishers by default, or a single publisher when `publisherId` is supplied.

Parameters

facilityId `string` (required) publisherId `string` (optional) startDate `string` (required) endDate `string` (required)

Endpoint

GET /api/facilities/{facilityId}/directory-insights

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/directory-insights \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get aggregated listing insights for a brand across all publishers.

Parameters

brandId `string` (required) startDate `string` (required) endDate `string` (required)

Endpoint

GET /api/brands/{brandId}/directory-insights

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId}/directory-insights \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Top search keywords (with branded/unbranded split) for a facility, currently sourced from Google Business Profile.

Parameters

facilityId `string` (required) publisherId `string` (optional) Defaults to "google" — only Google is supported today. startDate `string` (required) endDate `string` (required) limit `string` (optional)

Endpoint

GET /api/facilities/{facilityId}/directory-search-keywords

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/directory-search-keywords \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Top search keywords for a brand, aggregated across all facilities.

Parameters

brandId `string` (required) startDate `string` (required) endDate `string` (required) limit `string` (optional)

Endpoint

GET /api/brands/{brandId}/directory-search-keywords

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/brands/{brandId}/directory-search-keywords \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List Q&A for a facility.

Parameters

facilityId `string` (required)

Endpoint

GET /api/facilities/{facilityId}/qna

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/qna \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Answer a question.

Endpoint

POST /api/facilities/{facilityId}/qna/{questionId}/answer

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/facilities/{facilityId}/qna/{questionId}/answer \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete an answer.

Endpoint

DELETE /api/facilities/{facilityId}/qna/{questionId}/answer/{answerId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/facilities/{facilityId}/qna/{questionId}/answer/{answerId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all sync log entries, optionally filtered.

Parameters

publisherId `string` (optional) organisationId `string` (optional) facilityId `string` (optional) Restrict to a single facility (used by the customer Directory Management page).

Endpoint

GET /api/admin/directory-sync/status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/directory-sync/status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually trigger sync for a specific facility or all facilities.

Endpoint

POST /api/admin/directory-sync/trigger

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/directory-sync/trigger \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Set or clear the publisher-side `externalId` for a (facility, publisher) pair. Used by the Bind dialog so admins can attach a PH facility to an existing publisher listing instead of letting the worker auto-create a duplicate. Pass `externalId: null` (or empty string) to unbind.

Endpoint

PUT /api/admin/directory-sync/binding

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/directory-sync/binding \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Fan out a sync for every enabled+connected (facility, publisher) pair under the given organisation.

Endpoint

POST /api/admin/directory-sync/trigger-all

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/directory-sync/trigger-all \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get shared Door/Gate Access settings for a facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/rules/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/rules/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update shared Door/Gate Access settings for a facility

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/door-access/rules/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/rules/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get Access Policies for a facility

Existing access configuration is automatically converted to equivalent enforced policies on first read.

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/policies/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Replace Access Policies using optimistic revision checking

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/door-access/policies/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Create an Access Policy

Parameters

facilityId `string` (required)

Endpoint

POST /api/door-access/policies/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update one Access Policy

Parameters

facilityId `string` (required) policyId `string` (required)

Endpoint

PATCH /api/door-access/policies/{facilityId}/{policyId}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId}/{policyId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete one Access Policy

Parameters

facilityId `string` (required) policyId `string` (required) revision `integer` (required)

Endpoint

DELETE /api/door-access/policies/{facilityId}/{policyId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId}/{policyId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Duplicate an Access Policy with a new stable ID

Parameters

facilityId `string` (required) policyId `string` (required)

Endpoint

POST /api/door-access/policies/{facilityId}/{policyId}/duplicate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId}/{policyId}/duplicate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Count affected users and doors for all Access Policies

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/policies/{facilityId}/impacts

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId}/impacts \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Count users and doors affected by an Access Policy

Parameters

facilityId `string` (required) policyId `string` (required)

Endpoint

GET /api/door-access/policies/{facilityId}/{policyId}/impact

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/policies/{facilityId}/{policyId}/impact \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List person types, statuses, and tags for the facility

Returns the distinct person-type, membership-status, and tag values present on the facility's User Access rows (ph-door-access-users), derived from partner sync + manual entry. The door-gate-access applet uses these to populate the access-rules dropdowns. Tags are the union of synced `tags` and admin `customTags`, matching the rule evaluator.

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/people-config/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/people-config/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List door controllers at a facility with their effective Door/Gate Access rules

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/doors/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Save per-door overrides, icon, and device-side configuration

Single write surface for everything the DGA admin applet edits on a door: - `accessRulesOverride` / `geofenceOverride` — pass `null` to clear and fall back to the facility default. - `icon` — stable wire key (see services/door-access/door-icons.js); unknown values 400. - `holdTimeSeconds` (1\u201330), `maintenanceMode` (`off` / `force-open` / `force-closed`), `doorLocation` (free text, \u226464 chars), `playNotificationSoundOnRelayToggle` (boolean), `autoUnlockSchedule` (weekly window grid). These used to be Device-Management-only fields but the applet now writes them in-place so admins don't need to leave the door drawer for everyday config changes. When any of the device-side fields are touched the route also pushes the matching Balena env vars (`RELAY_NOTIFICATION_SOUND`, `DOOR_MAINTENANCE_MODE`, `DOOR_AUTO_UNLOCK_SCHEDULE`) and fires an `unlockUpdates` MQTT command so the device picks up the new config without waiting for the next Balena env refresh. Best-effort \u2014 the response 200s even if Balena is temporarily unreachable.

Parameters

facilityId `string` (required) doorId `string` (required)

Request Body

Endpoint

PUT /api/door-access/doors/{facilityId}/{doorId}/override

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId}/{doorId}/override \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Lightweight Balena-status probe for the door drawer's reload notice

The DGA applet's drawer fetches this lazily when an admin opens a door so it can show the right "saving will reload the controller" copy: the default "a few seconds" variant, or the stronger "several minutes" variant when a release update is also pending. Returns a flat snapshot derived from `balena.models.device.get()`. Soft-fails to `data: null` (rather than 5xx-ing) so a Balena outage degrades the notice copy instead of blocking the drawer from opening.

Parameters

facilityId `string` (required) doorId `string` (required)

Endpoint

GET /api/door-access/doors/{facilityId}/{doorId}/device-status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId}/{doorId}/device-status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Admin override — unlock a door from the applet

Briefly toggles the relay using the door's current `holdTimeSeconds`, writing an `admin-override` audit row to ph-door-app-access-events so the action is attributable in the Access Logs. Always succeeds regardless of `maintenanceMode === 'force-closed'` — this is the admin escape hatch. Returns 200 as soon as the MQTT publish is dispatched; confirmed / failed / timed_out states are not waited for here (the legacy /api/devices/door-controllers + /api/ics/devices/command flow is fire-and-forget too).

Parameters

facilityId `string` (required) doorId `string` (required)

Endpoint

POST /api/door-access/doors/{facilityId}/{doorId}/unlock

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId}/{doorId}/unlock \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Play a locator beep pattern on the door controller

Publishes a `beep` MQTT command so the controller emits three medium-length beeps (~500 ms each, ~350 ms gap, ~2 s total). Used by admins to physically locate a door controller on-site. The legacy Device Management button uses a ~30 s burst of short beeps but the firmware buzzer driver only reliably emits the first one, so the applet sends a shorter, more reliable pattern instead. No audit row \u2014 diagnostic action with no access-control side effect.

Parameters

facilityId `string` (required) doorId `string` (required)

Endpoint

POST /api/door-access/doors/{facilityId}/{doorId}/identify

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId}/{doorId}/identify \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remotely reboot a door controller

Publishes the same fire-and-forget `rebootDevice` MQTT command the legacy Device Management "Remotely Reboot Device" button sends, but gated by the `door-gate-access` module so DGA admins can reboot a controller from the door drawer's Advanced section without a separate `device-management` grant. Returns 200 as soon as the publish is dispatched; the device drops offline for the duration of the reboot.

Parameters

facilityId `string` (required) doorId `string` (required)

Endpoint

POST /api/door-access/doors/{facilityId}/{doorId}/reboot

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/doors/{facilityId}/{doorId}/reboot \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List User Access rows at a facility

Returns every non-deleted user-access row at the facility. Supports client-side filters (source, search, accessEnabled, hasGrants). The Phase 4 `hideExcluded` server-side computation will be added once the hybrid grants evaluator lands; for now the param is accepted but returns the full set.

Parameters

facilityId `string` (required) search `string` (optional) source `string` (optional) accessEnabled `string` (optional) hasGrants `string` (optional) hideExcluded `boolean` (optional) When true, synced users (source != manual) who could not pass any door at any time at this facility are hidden. The response includes a `hidden: { count, sample }` envelope.

Endpoint

GET /api/door-access/users/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/users/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Manually create a User Access row at a facility

Mints a new row with `source: 'manual'`. Returns 409 with `existingUserId` if the supplied phone or email already maps to a row at this facility.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/users/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Get a single User Access row

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

GET /api/door-access/users/{facilityId}/{userId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Partial update of a User Access row

Edits any subset of identity / authorization fields. Pass `null` to clear an optional field. Returns 409 if the new phone or email collides with another row at the same facility. `appMessage` accepts the same shape as the facility-wide message on PUT /api/door-access/rules/{facilityId} — body text, severity, optional link, optional start/end schedule. The mobile app shows this on the dashboard only for the targeted user.

Parameters

facilityId `string` (required) userId `string` (required)

Request Body

Endpoint

PATCH /api/door-access/users/{facilityId}/{userId}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Soft-delete a User Access row

Marks the row `deleted: true` and disables access. Audit-log linkage to the userId is preserved; admins can re-enable manually.

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

DELETE /api/door-access/users/{facilityId}/{userId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Per-door access attribution for a user

For every door, returns current deterministic authorization (`allowedNow`, `allowedVia`, `deniedReason`) and configured paths for Access Policies, permanent grants, policy schedules, admin time-window grants, and fresh mapped partner source windows. Also returns active/next availability and source freshness. Door blockAllAccess and maintenance are evaluated before all allow paths.

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

GET /api/door-access/users/{facilityId}/{userId}/effective-access

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/effective-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bulk-create User Access rows from a CSV import

Creates multiple `source: 'manual'` rows in one request, reusing the same validation, phone/email normalisation, per-facility collision check, auto-messaging and (optional) invite logic as the single create. Rows are processed in order, so a later row colliding with an earlier-created one is reported as a duplicate. Grants are supplied as already-resolved door/group IDs (the client resolves names to IDs). Time-window grants are intentionally rejected in bulk and must be added through the per-user replacement endpoint after import. Never throws per-row; each row's outcome is reported individually.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/users/{facilityId}/bulk

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/bulk \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Replace the hybrid-authorization grants on a User Access row

Phase 3 hybrid evaluator wire. Grants live alongside facility tag rules — a user is allowed when either matches at unlock time.

Parameters

facilityId `string` (required) userId `string` (required)

Request Body

Endpoint

PUT /api/door-access/users/{facilityId}/{userId}/grants

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/grants \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Replace additive Access Time Window grants on a User Access row

Replaces only `timeWindowGrants`; permanent `grants` and integration `sourceTimeWindows` are untouched. Each item requires a scope (`facilityWide`, `doors`, or `groups`) and an absolute or weekly `window`. Sending an empty array explicitly clears all admin windows.

Parameters

facilityId `string` (required) userId `string` (required)

Request Body

Endpoint

PUT /api/door-access/users/{facilityId}/{userId}/time-window-grants

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/time-window-grants \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Freeze a User Access row against source-driven sync updates

Sets `decoupledFromSource: true`, clears all integration-owned `sourceTimeWindows`, and makes sync (cron + streams) log + skip this row until an admin clears the flag via /recouple.

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

POST /api/door-access/users/{facilityId}/{userId}/decouple

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/decouple \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Re-attach a User Access row to source-driven sync updates

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

POST /api/door-access/users/{facilityId}/{userId}/recouple

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/recouple \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Revoke all Door/Gate Access app refresh tokens for a user

Revokes by the user's stored phone/email (the refresh-token table is keyed by `sha256(plaintext)`; the byMobilePhone / byEmail GSIs let us fan-out delete from a single user). Other users sharing the same phone/email at a different facility would also be signed out.

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

POST /api/door-access/users/{facilityId}/{userId}/logout

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/logout \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

(Re)send the Door/Gate Access app invitation email to a user

Force-sends the app-download invitation email to the user's stored email address (email only; no SMS). Ignores the eligibility and already-sent guards used by the automatic sync path — this is an explicit admin action. Returns 400 if the user has no email on file.

Parameters

facilityId `string` (required) userId `string` (required)

Endpoint

POST /api/door-access/users/{facilityId}/{userId}/resend-invite

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/{userId}/resend-invite \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Preview the recipients of a bulk app-invitation send

Computes the set of users who would receive an app invitation email. The base pool is every non-deleted user with an email who has never used the app (`appLastSeenAt` empty). By default the pool is narrowed to users who currently have access (rule match or grant) and have never been invited; `includeAlreadyInvited` and `includeNoAccess` widen it. No emails are sent — returns counts, a small sample, and the candidate userIds for the execute endpoint.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/users/{facilityId}/bulk-invite/preview

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/bulk-invite/preview \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Send app invitation emails to a batch of users

Sends the app-download invitation email to each of the supplied userIds (max 50 per request; the client batches the full candidate list from the preview). Each user is re-validated at send time — rows that no longer exist, have no email, or have used the app since the preview are skipped, never failed. Per-user outcomes are reported individually so the client can summarise sent / failed / skipped.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/users/{facilityId}/bulk-invite

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/users/{facilityId}/bulk-invite \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List Door Groups at a facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/door-groups/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/door-groups/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a Door Group

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/door-groups/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/door-groups/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Get a single Door Group

Parameters

facilityId `string` (required) groupId `string` (required)

Endpoint

GET /api/door-access/door-groups/{facilityId}/{groupId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/door-groups/{facilityId}/{groupId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a Door Group

Parameters

facilityId `string` (required) groupId `string` (required)

Request Body

Endpoint

PATCH /api/door-access/door-groups/{facilityId}/{groupId}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/door-access/door-groups/{facilityId}/{groupId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Soft-delete a Door Group

Parameters

facilityId `string` (required) groupId `string` (required)

Endpoint

DELETE /api/door-access/door-groups/{facilityId}/{groupId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/door-access/door-groups/{facilityId}/{groupId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List the partner integrations configured at a facility

Returns the facility's partner integrations (id, name, logo, enabled) by joining ph-facility-partner-config with the ph-partners catalog. Door-gate-access-scoped (so admins without external-integrations access can still render partner badges and the per-partner sync list).

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/partners/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/partners/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Read the User Access sync config for a facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/sync-config/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/sync-config/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the User Access sync config for a facility

Only the admin-controlled fields (`enabled`, `requireIdentifier`, and the partner `partners` map) are accepted; `lastRunAt` and `lastRunCounts` are written by the sync engine itself. `partner.partners` is a per-partner enable map keyed by partnerId (opt-out): when the master `partner.enabled` is on, a partner syncs unless it has an explicit `{ enabled: false }` entry here.

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/door-access/sync-config/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/sync-config/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Read the automated per-user messaging config for a facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/auto-messages/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/auto-messages/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the automated per-user messaging config for a facility

Saves the rules, then immediately re-evaluates every User Access row at the facility so existing users get/lose their automated message right away. Manual messages and decoupled rows are left untouched.

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/door-access/auto-messages/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/auto-messages/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Status of the background auto-message re-evaluation sweep

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/auto-messages/{facilityId}/sweep-status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/auto-messages/{facilityId}/sweep-status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Run an on-demand User Access sync for a facility

Synchronously sweeps every enabled source (partner / cctv) at the facility and converges ph-door-access-users rows via the dedup waterfall. Returns per-source counts. Disabled sources show up as `skippedSyncDisabled: 1` rather than absent so the UI can render both rows consistently.

Parameters

facilityId `string` (required)

Endpoint

POST /api/door-access/sync/{facilityId}/run

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/sync/{facilityId}/run \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Dry-run preview of a partner-synced bulk delete

Returns the count + a sample of the user-access rows that would be soft-deleted, plus a confirmToken that must be echoed back to the execute endpoint. No data is modified. Access logs are never affected.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/sync/{facilityId}/bulk-delete/preview

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/sync/{facilityId}/bulk-delete/preview \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Execute a partner-synced bulk delete (soft delete)

Soft-deletes every partner-synced user-access row in scope. Requires the confirmToken returned by the preview; if the live set has changed since the preview the token won't match and the request is rejected (409) so the admin re-reviews. Access logs are preserved.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/door-access/sync/{facilityId}/bulk-delete

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/sync/{facilityId}/bulk-delete \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Recent User Access sync activity (troubleshooting log)

Returns the most recent sync outcomes for a facility (created / skipped / disabled) with the reason, so admins can see why a member did or didn't sync. Newest first.

Parameters

facilityId `string` (required) limit `integer` (optional)

Endpoint

GET /api/door-access/sync/{facilityId}/log

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/sync/{facilityId}/log \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List Door/Gate Access events for a facility

Returns mobile, admin override, and external Partner API unlock events in one reverse-chronological feed.

Parameters

facilityId `string` (required) from `integer` (optional) to `integer` (optional) limit `integer` (optional)

Endpoint

GET /api/door-access/events/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/events/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Dry-run a geofence evaluation for the admin test-mode pin

Request Body

Endpoint

POST /api/door-access/geofence/test

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/door-access/geofence/test \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get the onboarding / activation status for a facility

Drives the applet's "Get Started" landing and setup-progress banner. Returns live door + user counts, the two derived core steps (a user exists, a door exists), the persisted optional "reviewed" flags, and whether the facility is activated (both core steps done). The first time a facility becomes activated the activatedAt timestamp is stamped.

Parameters

facilityId `string` (required)

Endpoint

GET /api/door-access/onboarding/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/door-access/onboarding/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the optional onboarding "reviewed" flags for a facility

Persists the optional setup-checklist flags an admin ticks off (access rules, sync settings, geofencing). The core steps and activation are derived live from data counts and cannot be set here. Returns the full refreshed onboarding status.

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/door-access/onboarding/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/door-access/onboarding/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/lead-events

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/lead-events \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/page-views

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/page-views \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/referrers

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/referrers \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/socials

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/socials \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/top-cities

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/top-cities \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/total-page-views

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/total-page-views \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a JSON response of club analytics data.

Parameters

clubId `string` (optional) The club ID of the club to retrieve analytics data for. fromDate `string` (optional) The start date of the analytics data to retrieve. toDate `string` (optional) The end date of the analytics data to retrieve.

Endpoint

GET /clubs/{clubId}/analytics/traffic

Example Request

curl -X GET https://portal.hub.gymsystems.co/clubs/{clubId}/analytics/traffic \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generates a temporary front-end JWT (Json Web Token) for Google Analytics embeddable charts in the front-end 'analytics' page.

Endpoint

GET /api/ga/onetimetoken

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ga/onetimetoken \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns dashboard widgets from 'The Training Camp' if the club has any active members.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/reporting/apps/widgets/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/apps/widgets/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all unreviewed club holidays.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/reporting/club/{club}/unreviewed-holidays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/club/{club}/unreviewed-holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Set all unreviewed club holidays to reviewed.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

PUT /api/reporting/club/{club}/review-holidays

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/reporting/club/{club}/review-holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the KPI Report in a CSV format, broken down in a month-by-month basis over the last 12 months. *NOTE* This creates a single report for ALL Clubs in the system - Do not run this multiple times in parallel or you will over-load GymMaster!

Parameters

months `string` (optional) Number of months (from current date) to fetch (defaults to 12)

Endpoint

GET /api/reporting/gymmaster/all-clubs-kpi-report

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/gymmaster/all-clubs-kpi-report \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the MMS's revenue graph(s) for a given club.

Parameters

club `string` (required) Internal ID of the club that you wish to access. range `string` (optional) Range in days (counting back from the current date) that we wan to fetch

Endpoint

GET /api/reporting/gymmaster/revenuegraph/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/gymmaster/revenuegraph/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the dashboard's MMS (Member Management System) data/analytics for a given club. Data includes GymMaster/Perfect Gym statistics as well as other internal metrics collected by our system.

Parameters

club `string` (required) Internal ID of the club that you wish to access. range `string` (optional) Range in days (counting back from the current date) that we wan to fetch

Endpoint

GET /api/reporting/gymmaster/widgets/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/gymmaster/widgets/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the dashboard's Myzone widget data for a given club.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/reporting/myzone/widgets/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/myzone/widgets/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns an object of services which are deemed offline from one or more of our status page/monitoring endpoints - configured via internal 'Uptime Kuma' tool.

Endpoint

GET /api/reporting/statuspage/events

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/statuspage/events \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns upcoming workout bookings for the next 7 days.

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/reporting/clubs/{club}/workout-bookings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/reporting/clubs/{club}/workout-bookings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of historical club holidays for a club.

Parameters

clubId `string` (optional) Club ID fromDate `string` (optional) Unix timestamp of the start date of the range of holidays to return. toDate `string` (optional) Unix timestamp of the end date of the range of holidays to return.

Endpoint

GET /api/clubs/{clubId}/historical-holidays

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubId}/historical-holidays \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns device automations associated with club.

Parameters

club `string` (required) Internal ID of the club that you wish to list devices from.

Endpoint

GET /api/ics/automations/list/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/automations/list/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the device configuration for an existing display/device.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/ics/automations/update/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/automations/update/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add a new data source for the screen display UI.

Parameters

name `string` (required) Name of the data source type `string` (required) Data source type langShort `string` (required) Short language name lang `string` (optional) Language code data `string` (optional) JSON string of data for static types

Endpoint

POST /api/ics/data-sources

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/data-sources \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List data sources for the screen display UI.

Endpoint

GET /api/ics/data-sources

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/data-sources \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update data source for the screen display UI.

Parameters

id `string` (required) Unique identifier of the data source generated upon creation name `string` (optional) Name of the data source type `string` (optional) Data source type langShort `string` (optional) Short language name lang `string` (optional) Language code data `string` (optional) JSON string of data for static types

Endpoint

PUT /api/ics/data-sources

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ics/data-sources \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/associates a physical screen device/computer with your club.

Parameters

club `string` (required) Internal ID of the club that you wish to add the device under. body `string` (required) Json Object of the new screen to associate with.

Endpoint

POST /api/ics/devices/add/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/devices/add/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Instructs device to connect to new SSID based on parameters.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/ics/devices/changewifi/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/devices/changewifi/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the device configuration for an existing display/device.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/ics/devices/command/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/devices/command/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Loads a URL/webpage on a specific device screen.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

POST /api/ics/devices/loadurl/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/devices/loadurl/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the device configuration for an existing display/device.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) Json Object of the update parameters.

Endpoint

PUT /api/ics/devices/update/{club}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ics/devices/update/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Renames a display/device. Registration-only - unlike the update endpoint this pushes nothing to the device, so it is also available for screens running an end-of-life software build.

Parameters

club `string` (required) Internal ID of the club the device belongs to. body `string` (required) Json Object of the rename parameters.

Endpoint

PUT /api/ics/devices/rename/{club}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ics/devices/rename/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets widgets and links to off-line media for a club, based on the supplied date.

Parameters

club `string` (required) Internal ID of the club that you wish to change the workout program to. date `string` (required) Date to return widget URLs - Use `YYYY-MM-DD` format.

Endpoint

GET /api/ics/external-resources/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/external-resources/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets widgets and links to off-line media for a club, based on the supplied date.

Parameters

club `string` (required) Internal ID of the club that you wish to change the workout program to.

Endpoint

GET /api/ics/list-scheduled-workouts/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/list-scheduled-workouts/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Changes the workout program for a given club.

Parameters

club `string` (required) Internal ID of the club that you wish to change the workout program to. body `string` (required) Json Object of the new workout to change.

Endpoint

POST /api/ics/loadprogram/{club}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/loadprogram/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieves the program configuration for an existing display/device.

Parameters

club `string` (required) Internal ID of the club that you wish to retrieve program data of.

Endpoint

GET /api/ics/programs/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/programs/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the program configuration for an existing display/device.

Parameters

club `string` (required) Internal ID of the club that you wish to update the device. body `string` (required) JSON Object of the update parameters.

Endpoint

PUT /api/ics/programs/{club}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ics/programs/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieves the program configuration options.

Endpoint

GET /api/ics/programs/options/{facilityID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/programs/options/{facilityID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add a new UI option for the screen displays.

Parameters

name `string` (required) Name of the UI Option description `string` (required) Short description about this UI url `string` (required) Base URL of the UI

Endpoint

POST /api/ics/ui-options

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ics/ui-options \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List UI options for the screen displays.

Endpoint

GET /api/ics/ui-options

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ics/ui-options \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update UI option for the screen displays.

Parameters

id `string` (required) Unique identifier of the data source generated upon creation name `string` (optional) Name of the UI Option description `string` (optional) Short description about this UI url `string` (optional) Base URL of the UI

Endpoint

PUT /api/ics/ui-options

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/ics/ui-options \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Queue wiki articles for embedding by synchronising embedding track entries

Request Body

Endpoint

POST /api/llm/articles/queue-sync

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/articles/queue-sync \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Chat with RAG context - This does not have access to tools - only a simple API request|response tool that lets you directly pull knowledge from the knowledge base.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Request Body

Endpoint

POST /api/llm/chat

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/chat \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete article embeddings from vector store and update embedding track status

Request Body

Endpoint

DELETE /api/llm/delete-article

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/llm/delete-article \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List embedding tracker records by organisation and status

Parameters

organisationId `string` (optional) Organisation ID (auto-resolved if omitted) status `string` (required) Status to filter by (must be one of in_queue, done, anomaly, fail, deleted) Limit `string` (optional) Max items per page LastEvaluatedKey `string` (optional) JSON of DynamoDB LastEvaluatedKey for pagination

Endpoint

GET /api/llm/embedding-track/by-org-and-status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/embedding-track/by-org-and-status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List embedding tracker records by organisation (optionally filter by resource type)

Parameters

organisationId `string` (optional) Organisation ID (auto-resolved if omitted) resourceType `string` (optional) Optional resource type (e.g., "article"). When provided, filters where resourceTypeId begins with "{type}#". Limit `string` (optional) Max items per page LastEvaluatedKey `string` (optional) JSON of DynamoDB LastEvaluatedKey for pagination

Endpoint

GET /api/llm/embedding-track/by-org

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/embedding-track/by-org \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initialize organization vector database collection

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Endpoint

POST /api/llm/init-org

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/init-org \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Trigger reindex of knowledge base

Fetches all published wiki articles for the organisation and generates/updates embeddings in the vector store. This process can take several minutes depending on the number of articles.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Request Body

Endpoint

POST /api/llm/reindex

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/reindex \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Semantic search in knowledge base

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Request Body

Endpoint

POST /api/llm/semantic-search

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/semantic-search \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Start streaming processing of queued articles for embedding with real-time progress updates

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Endpoint

POST /api/llm/start-embedding-stream

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/start-embedding-stream \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upsert article embeddings into vector database

Handles article embedding based on current state: - If article is unpublished OR private: deletes embeddings - If article is published AND public: re-embeds with full content Always requires full article body.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Request Body

Endpoint

POST /api/llm/upsert-embeddings

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/upsert-embeddings \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Test endpoint to batch delete article embeddings by organization and optional status

Parameters

organisationId `string` (optional) Organisation ID (auto-resolved from user context if omitted) status `string` (optional) Status to filter by (optional - if omitted, deletes ALL articles for the organization regardless of status) hardDelete `string` (optional) Whether to hard delete embedding track records (true) or soft delete by updating status (false)

Endpoint

DELETE /api/llm/test/batch-delete-by-status

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/llm/test/batch-delete-by-status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Transform and chunk text with detailed statistics

Test endpoint that transforms text and chunks it, then provides detailed statistics about chunk distribution including character counts, percentages, and quality metrics to help evaluate chunking effectiveness.

Request Body

Endpoint

POST /api/llm/test/transform-chunk

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/test/transform-chunk \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get total count of vectors in vector index for organization

Test endpoint to count all vectors in the vector index for the current user's organization

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Endpoint

GET /api/llm/test/vector-count

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/test/vector-count \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete all vectors for a specific articleId from vector index

Test endpoint to delete all vectors associated with a specific articleId from the vector index for the current user's organization.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided) articleId `string` (required) The articleId to delete vectors for dryRun `string` (optional) If true, only shows what would be deleted without actually deleting

Endpoint

DELETE /api/llm/test/vector-delete-article

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/llm/test/vector-delete-article \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Test Vector SDK by listing all indexes

Test endpoint to verify Vector SDK connectivity and list all indexes in the vector bucket

Endpoint

GET /api/llm/test/vector-indices

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/test/vector-indices \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initialize Vector index for an organization

Creates the Vector bucket and index for the current user's organization

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided)

Endpoint

POST /api/llm/test/vector-init-index

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/llm/test/vector-init-index \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get all vector metadata for a specific articleId

Test endpoint to retrieve all vector chunks and their metadata for a specific articleId from the vector index. Useful for inspecting how an article is chunked and stored. Filtering is handled by the vector store service.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided) articleId `string` (required) The article ID to retrieve vector metadata for

Endpoint

GET /api/llm/test/vector-metadata-by-article

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/test/vector-metadata-by-article \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get recent vectors with metadata from vector index

Test endpoint to retrieve the 10 most recent vectors with metadata (but without vector data) from the vector index for the current user's organization. Useful for inspecting metadata structure.

Parameters

organisationId `string` (optional) The organisation ID (will be auto-detected if not provided) limit `string` (optional) Number of recent vectors to return (max 100)

Endpoint

GET /api/llm/test/vector-recent

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/llm/test/vector-recent \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Uploads an asset for the Marketing Manager/Designer to S3 Storage.

Parameters

file `string` (optional) Name of the file/asset to be uploaded.

Endpoint

POST /api/marketing/design/static/download

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/marketing/design/static/download \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the individual assets JSON format to be loaded into the asset manager.

Parameters

id `string` (required) ID of the asset to get. organisationId `string` (required) The organisation ID of the facility that the asset belongs to.

Endpoint

GET /api/marketing/assets/get/{id}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/assets/get/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retuns all design assets.

Parameters

body `string` (required) Json Object of club data that you wish to save. organisationId `string` (required) The organisation ID of the facility that the asset belongs to. useCache `string` (optional) search `string` (optional) The search query to filter assets by name or tags. brand `string` (optional) The brand to filter assets by. tag `string` (optional) The tag to filter assets by.

Endpoint

GET /api/marketing/assets/get

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/assets/get \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a single page of marketing print assets for an organisation. Uses Algolia for relevance search + page-based pagination (with total counts), and falls back to DynamoDB when Algolia is unavailable.

Parameters

organisationId `string` (required) The organisation ID of the facility that the assets belong to. search `string` (optional) The search query to filter assets by name or tags. brand `string` (optional) The brand to filter assets by. tag `string` (optional) The tag to filter assets by. page `string` (optional) Zero-indexed page number to fetch. limit `string` (optional) Number of assets per page (max 300). useCache `string` (optional) When false, bypasses Algolia and queries DynamoDB directly.

Endpoint

GET /api/marketing/assets

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/assets \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of available assets that have been uploaded via the asset manager.

Parameters

organisationId `string` (required)

Endpoint

GET /api/marketing/assets/list

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/assets/list \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Saves an asset.

Parameters

body `string` (required) Json Object of club data that you wish to save. organisationId `string` (required) The organisation ID of the facility that the asset belongs to.

Endpoint

PUT /api/marketing/assets/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/marketing/assets/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Uploads an asset for the Marketing Manager/Designer to S3 Storage.

Parameters

file `string` (optional) Name of the file/asset to be uploaded. organisationId `string` (optional) The ID of the organisation the asset belongs to.

Endpoint

POST /api/marketing/assets/upload

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/marketing/assets/upload \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of all custom pages for an organisation.

Parameters

organisationId `string` (required) Internal ID of the organisation to return custom pages for.

Endpoint

GET /api/marketing/custom-pages

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/custom-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Upserts a custom page for an organisation.

Parameters

organisationId `string` (required) Internal ID of the organisation to return custom pages for. body `object` (required) Custom page data to upsert.

Endpoint

PUT /api/marketing/custom-pages

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/marketing/custom-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of all custom pages for a facility.

Parameters

facilityId `string` (required) Internal ID of the facility to return custom pages for.

Endpoint

GET /api/facilities/{facilityId}/marketing/custom-pages

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/facilities/{facilityId}/marketing/custom-pages \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all exported/rendered designs for a specific club id.

Parameters

club `string` (required) Internal ID of the club that is making the request. sort `string` (optional) Filter to sort designs by, 'oldest', 'newest', or 'design' supported.

Endpoint

GET /api/marketing/designs/{club}/exports

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/{club}/exports \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the individual HTML contents for a design in JSON format to be loaded into the editor.

Parameters

id `string` (required) ID of the design to get.

Endpoint

GET /api/marketing/designs/get/{id}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/get/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of input mapping in marketing and print designs and design templates

Parameters

clubId `string` (required) Internal ID of the club that is making the request. availableFeatures `string` (optional) Return all items with specific features brand `string` (optional) Filters designs by brand features `string` (optional) Filter results based on features

Endpoint

GET /api/marketing/designs/input-mapping/{clubId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/input-mapping/{clubId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of available designs for a given club, that may be used within designs (Print Designs) created within the hub's marketing/print editor.

Parameters

club `string` (required) Internal ID of the club that is making the request. designAdmin `string` (optional) Return all design data (admin view / requires user to be administrator). brand `string` (optional) Filters designs by brand

Endpoint

GET /api/marketing/designs/{club}/list

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/{club}/list \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Forces the system to render/re-render all design thumbnails & previews (Used mainly if we change 'upstream' assets in S3 etc)... **NOTE** You can only call this function once per X minutes (or if a render is already-running you can't call this function). This is to ensure that we don't put excess load on our servers rendering all designs...

Endpoint

GET /api/marketing/designs/render-all-thumbnails

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/render-all-thumbnails \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Initiates render of a Dynamic Design

Parameters

body `string` (required) Json Object of club data you wish to send to the design render processor...

Endpoint

POST /api/marketing/designs/dynamic/render-design

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/marketing/designs/dynamic/render-design \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Saves/Updates a design.

Parameters

body `string` (required) Json Object of club data that you wish to save.

Endpoint

PUT /api/marketing/designs/{club}/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/marketing/designs/{club}/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the individual static design JSON format to be loaded

Parameters

id `string` (required) ID of the static design to get.

Endpoint

GET /api/marketing/designs/static/get/{id}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/designs/static/get/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Saves/Updates an static design template.

Parameters

body `string` (required) Json Object of club data that you wish to save.

Endpoint

PUT /api/marketing/designs/static/{club}/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/marketing/designs/static/{club}/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Removes a user set variable from the system.

Parameters

club `string` (required) Internal ID of the club that is making the request. body `string` (required) Json containing the variable ID to remove.

Endpoint

DELETE /api/marketing/variables/{club}/delete

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/marketing/variables/{club}/delete \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of available variables for a given club, that may be used within designs (Print Designs) created within the hub's marketing/print editor.

Parameters

club `string` (required) Internal ID of the club that is making the request.

Endpoint

GET /api/marketing/variables/{club}/list

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/marketing/variables/{club}/list \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a single new user based 'variable' for the given club.

Parameters

club `string` (required) Internal ID of the club that is making the request. body `string` (required) Json Object of the new variable.

Endpoint

POST /api/marketing/variables/{club}/new

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/marketing/variables/{club}/new \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Adds/Saves/Updates one or more design variables in the system via an array of objects.

Parameters

club `string` (required) Internal ID of the club that is making the request. body `string` (required) Array of One or more Json Object's to be added/updated (This allows for saving of multiple items/objects in one API request).

Endpoint

PUT /api/marketing/variables/{club}/save

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/marketing/variables/{club}/save \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the MCP documentation manifest for the signed-in user

Powers the in-app `/mcp-docs` page. Returns the MCP server URL, the supported auth headers, the caller's identity/admin flag, and the filtered tool list (filtered identically to `/mcp/tools/list`, so the docs page never shows a tool the caller cannot actually use).

Endpoint

GET /api/mcp/docs-manifest

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/mcp/docs-manifest \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create user agreement.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

POST /api/member-agreements/contracts-tna/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/member-agreements/contracts-tna/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of agreement.

Endpoint

GET /api/member-agreements/contracts-tna/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/member-agreements/contracts-tna/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete user agreement.

Endpoint

DELETE /api/member-agreements/contracts-tna/:club/:id

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/member-agreements/contracts-tna/:club/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns specific of agreement.

Endpoint

GET /api/member-agreements/contracts-tna/:club/:id

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/member-agreements/contracts-tna/:club/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update user agreement.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

PATCH /api/member-agreements/contracts-tna/:club/:id

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/member-agreements/contracts-tna/:club/:id \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get default agreeents of the club.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

GET /api/member-agreements/default-tna/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/member-agreements/default-tna/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Set default agreeent of the club.

Parameters

body `object` (required) Json Object of club data that you wish to save.

Endpoint

POST /api/member-agreements/default-tna/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/member-agreements/default-tna/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of global or region agreement.

Endpoint

GET /api/member-agreements/global-tna/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/member-agreements/global-tna/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of members with agreement.

Endpoint

GET /api/member-agreements/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/member-agreements/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all members, combined from all GymMaster API Endpoints configured in the system.

Parameters

export `string` (optional) Return/Export results as a CSV File for import to other systems. trainingcamp `string` (optional) Choses to export the data from the DB "as is", or in a format that can be imported into MailChimp for "The Training Camp". status `string` (optional) Allows to filter members by a specific status - ie "Expired", "Current" etc draw `string` (optional) Enable/disable Datatables Response Pagination by specifying the Draw search `string` (optional) Search Database for specific querystring... length `integer` (optional) Number of items to return when using Datatables pagination ExclusiveStartKey `string` (optional) The "start" key/index (should be an object) to start returning data from (in the database) when paging through multiple pages...

Endpoint

GET /api/members-leads/gymmaster/all/members

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/gymmaster/all/members \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of ALL train at home registrations from the mobile v1 app.

Parameters

export `string` (optional) Return/Export results as a CSV File for import to other systems. draw `string` (optional) Enable/disable Datatables Response Pagination by specifying the Draw search `string` (optional) Search Database for specific querystring... length `integer` (optional) Number of items to return when using Datatables pagination ExclusiveStartKey `string` (optional) The "start" key/index (should be an object) to start returning data from (in the database) when paging through multiple pages...

Endpoint

GET /api/members-leads/train-at-home/all/users

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/train-at-home/all/users \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of ALL Training Camp App members (For Hub admin Tools)

Parameters

export `string` (optional) Return/Export results as a CSV File for import to other systems. trainingcamp `string` (optional) Choses to export the data from the DB "as is", or in a format that can be imported into MailChimp for "The Training Camp". draw `string` (optional) Enable/disable Datatables Response Pagination by specifying the Draw search `string` (optional) Search Database for specific querystring... length `integer` (optional) Number of items to return when using Datatables pagination ExclusiveStartKey `string` (optional) The "start" key/index (should be an object) to start returning data from (in the database) when paging through multiple pages...

Endpoint

GET /api/members-leads/trainingcamp/all/app-members

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/trainingcamp/all/app-members \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of ALL Training Camp leads from the 12RND/UBX Websites (For Hub admin Tools)

Parameters

export `string` (optional) Return/Export results as a CSV File for import to other systems. trainingcamp `string` (optional) Choses to export the data from the DB "as is", or in a format that can be imported into MailChimp for "The Training Camp". draw `string` (optional) Enable/disable Datatables Response Pagination by specifying the Draw search `string` (optional) Search Database for specific querystring... length `integer` (optional) Number of items to return when using Datatables pagination ExclusiveStartKey `string` (optional) The "start" key/index (should be an object) to start returning data from (in the database) when paging through multiple pages...

Endpoint

GET /api/members-leads/trainingcamp/all/leads

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/trainingcamp/all/leads \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of club members by season for the training camp's app.

Parameters

club `string` (required) Internal ID of the club that you wish to access. season `string` (optional) Season of the training camp that you wish to filter. userIds `string` (optional) Array of user ids to filter. useCache `string` (optional) Whether to use the cache. isUserMemberInfo `string` (optional) If enabled, it will filter the data based on userIds (recommended to use only one user id) and include necessary data such as leaderboard and user preferences.

Endpoint

GET /api/members-leads/trainingcamp/club/season-members/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/trainingcamp/club/season-members/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of ALL Training Camp leads from the 12RND/UBX Websites (For Hub admin Tools)

Parameters

export `string` (optional) Return/Export results as a CSV File for import to other systems. draw `string` (optional) Enable/disable Datatables Response Pagination by specifying the Draw search `string` (optional) Search Database for specific querystring... length `integer` (optional) Number of items to return when using Datatables pagination ExclusiveStartKey `string` (optional) The "start" key/index (should be an object) to start returning data from (in the database) when paging through multiple pages...

Endpoint

GET /api/members-leads/website/all/leads

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/website/all/leads \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deletes multiple workout booking leads.

Parameters

club `string` (required) Internal ID of the club that you wish to access. body `string` (required)

Endpoint

DELETE /api/members-leads/workout-booking/club/leads/{club}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/members-leads/workout-booking/club/leads/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of a club's workout booking leads.

Parameters

club `string` (required) Internal ID of the club that you wish to access. all `string` (optional) To show all the leads or just the upcoming ones.

Endpoint

GET /api/members-leads/workout-booking/club/leads/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/members-leads/workout-booking/club/leads/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a workout booking lead.

Parameters

club `string` (required) Internal ID of the club that you wish to access. body `string` (required)

Endpoint

PUT /api/members-leads/workout-booking/club/leads/{club}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/members-leads/workout-booking/club/leads/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Toggles the flagged state of a workout booking lead.

Parameters

club `string` (required) Internal ID of the club. body `string` (required)

Endpoint

PATCH /api/members-leads/workout-booking/club/leads/{club}/flag

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/members-leads/workout-booking/club/leads/{club}/flag \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

get notification categories.

Endpoint

GET /api/notification/categories

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/notification/categories \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete notification consumed.

Endpoint

DELETE /api/club/notification/consumed/:club

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/club/notification/consumed/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

creates notification message.

Endpoint

POST /api/club/notification/consumed/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/club/notification/consumed/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns array of notification consumed.

Endpoint

GET /api/club/notification/consumed/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/notification/consumed/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete notification message.

Endpoint

DELETE /api/club/notification/messages/:club

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/club/notification/messages/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns array of notification messages.

Endpoint

GET /api/club/notification/messages/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/notification/messages/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

updates notification message.

Endpoint

PATCH /api/club/notification/messages/:club

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/club/notification/messages/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

creates notification message.

Parameters

body `string` (required)

Endpoint

POST /api/club/notification/messages/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/club/notification/messages/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

get the viewers of notification by club.

Endpoint

POST /api/club/notification/viewers/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/club/notification/viewers/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

get notification categories by user.

Endpoint

GET /api/club/notification/user-categories/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/club/notification/user-categories/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

creates notification message.

Endpoint

POST /api/notification/webhook

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/notification/webhook \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get VAPID public key for HTML5 push

Returns the VAPID public key used to create browser push subscriptions.

Endpoint

GET /html5-push/vapid-public-key

Example Request

curl -X GET https://portal.hub.gymsystems.co/html5-push/vapid-public-key \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Save or update a HTML5 push subscription

Persists a browser push subscription for the current user.

Request Body

Endpoint

POST /html5-push/subscribe

Example Request

curl -X POST https://portal.hub.gymsystems.co/html5-push/subscribe \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete a HTML5 push subscription

Removes a browser push subscription for the current user.

Request Body

Endpoint

POST /html5-push/unsubscribe

Example Request

curl -X POST https://portal.hub.gymsystems.co/html5-push/unsubscribe \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get the location onboarding status for the calling user

Returns the two onboarding portions for a facility — setup (details + product selections, stored on club preferences) and payment (derived live from the SaaS billing payment-settings record) — plus a caller personalised `required` flag the app shell gates on. Technology-stack locations only; business-stack locations always return required=false. Global admins are never gated.

Parameters

facilityId `string` (required)

Endpoint

GET /api/onboarding/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/onboarding/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Save in-flight onboarding wizard progress for a facility

Persists partial wizard state (product selections, "Other" free text, reviewed business details, current step) so refresh/abandon resumes where the user left off. Never stamps completion — see the complete endpoint.

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/onboarding/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/onboarding/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Generate AI prefill suggestions for the onboarding wizard

Uses the existing club/brand/organisation context to propose facility details (about copy, tidied contact fields), suggested product selections, and short personalised tips. Results are cached in Redis for 7 days. Suggestions are advisory only — the client renders them into an editable review form. Always responds 200; `suggestions` is null when AI is unavailable so the wizard degrades gracefully.

Parameters

facilityId `string` (required)

Endpoint

POST /api/onboarding/{facilityId}/ai-prefill

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/onboarding/{facilityId}/ai-prefill \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Complete the setup portion of location onboarding

Validates the confirmed selections/details, persists the business details to the club record, seeds the facility tech-menu layout from the product selections (unless a customised layout already exists), and stamps setup completion. The payment portion is intentionally NOT completable here — it is derived live from the SaaS billing payment-settings record, so the mandatory card requirement cannot be bypassed by calling this endpoint. Returns the refreshed status.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/onboarding/{facilityId}/complete

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/onboarding/{facilityId}/complete \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Trigger a declared partner integration action for a facility

Runs a "Run integration" action declared on the partner record (ph-partners.actions[]), scoped to a facility. A Redis single-flight lock prevents concurrent manual runs for the same action+facility.

Parameters

partnerId `string` (required) actionId `string` (required)

Request Body

Endpoint

POST /api/partners/{partnerId}/actions/{actionId}/run

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/{partnerId}/actions/{actionId}/run \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Read the run status of a partner integration action

Returns whether a manual run is currently in flight (single-flight lock held) plus the last requested run, for the settings button to poll.

Parameters

partnerId `string` (required) actionId `string` (required) facilityId `string` (required)

Endpoint

GET /api/partners/{partnerId}/actions/{actionId}/status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/{partnerId}/actions/{actionId}/status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add a new partner.

Parameters

name `string` (required) Name of the partner description `string` (optional) Short description of the partner details `string` (optional) Detailed information about the partner logoUrl `string` (optional) URL to the partner's logo image website `string` (optional) Partner's website URL category `string` (optional) Categories the partner belongs to allowedOrganisations `string` (optional) Array of organisation IDs that this partner is restricted to. Omit or pass empty array for no restriction. facilityConfigHtmlEmbed `string` (optional) Optional HTML snippet shared with facilities. Maximum size is 150 KB to respect DynamoDB item limits.

Endpoint

POST /api/partners

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all partners.

Endpoint

GET /api/partners

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a partner.

Parameters

partnerId `string` (required) ID of the partner name `string` (optional) Name of the partner description `string` (optional) Short description of the partner details `string` (optional) Detailed information about the partner logoUrl `string` (optional) URL to the partner's logo image website `string` (optional) Partner's website URL category `string` (optional) Categories the partner belongs to. Pass empty array to remove categories. allowedOrganisations `string` (optional) Array of organisation IDs that this partner is restricted to. Pass empty array to remove restriction. facilityConfigHtmlEmbed `string` (optional) Optional HTML snippet shared with facilities. Maximum size is 150 KB to respect DynamoDB item limits.

Endpoint

PUT /api/partners

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/partners \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get all partner configurations for a brand

Parameters

brandId `string` (required) The brand ID

Endpoint

GET /api/partners/brand-config/{brandId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/brand-config/{brandId} \
  -H "x-api-key: YOUR_API_KEY"

Response

[]

Create or update a brand partner configuration

Parameters

body `object` (required)

Endpoint

PUT /api/partners/brand-config

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/partners/brand-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a partner.

Parameters

partnerId `string` (required) ID of the partner

Endpoint

DELETE /api/partners/{partnerId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/partners/{partnerId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Generate an admin token for accessing partner console

Parameters

partnerId `string` (required) ID of the partner

Endpoint

POST /api/partners/generate-admin-token

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/generate-admin-token \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Migrate GymMaster integration data to facility-partner-config

Queries all clubs with gymMasterAPI and gymMasterDomain fields and creates/updates corresponding facility-partner-config records. This is a one-time migration endpoint.

Parameters

partnerId `string` (required) The GymMaster partner ID to use for all migrated records dryRun `boolean` (optional) If true, only reports what would be migrated without writing to database

Endpoint

GET /api/partners/migrate-gymmaster

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/migrate-gymmaster \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable a partner for an organisation.

Parameters

partnerId `string` (required) ID of the partner

Endpoint

POST /api/partners/organisation/enable

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/organisation/enable \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List organisation partners. Global admins see all, organisation admins see only their organisation's partners.

Endpoint

GET /api/partners/organisation

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/organisation \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Remove an organisation partner.

Parameters

keyId `string` (required) Key ID of the organisation partner organisationId `string` (required) Organisation ID of the partner

Endpoint

DELETE /api/partners/organisation/{keyId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/partners/organisation/{keyId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update organisation partner access mode and modules.

Parameters

keyId `string` (required) Key ID of the organisation partner organisationId `string` (required) Organisation ID of the partner partnerId `string` (required) Partner ID accessMode `string` (required) Access mode for the partner modules `string` (optional) List of modules for LIMITED access mode

Endpoint

PUT /api/partners/organisation/update-access

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/partners/organisation/update-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Send welcome email to a partner

Parameters

partnerId `string` (required) ID of the partner

Endpoint

POST /api/partners/send-welcome-email

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/send-welcome-email \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create check-ins for a facility

Accepts an array of check-in objects and forwards them to the Partner API for processing. Maximum of 25 check-ins per request.

Request Body

Endpoint

POST /api/partners/check-ins

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/check-ins \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete a partner configuration for a facility

Removes the configuration for a partner integration at a facility

Parameters

facilityId `string` (required) Facility ID (club ID) partnerId `string` (required) Partner ID

Endpoint

DELETE /api/partners/facility-config/{facilityId}/{partnerId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/partners/facility-config/{facilityId}/{partnerId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List all partner configurations for a facility

Returns all partner integrations configured for the given facility

Parameters

facilityId `string` (required) Facility ID (club ID)

Endpoint

GET /api/partners/facility-config/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/facility-config/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update a partner configuration for a facility

Upserts the configuration for a partner integration at a facility

Request Body

Endpoint

POST /api/partners/facility-config

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/facility-config \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete a member by memberId

Deletes an existing member record using the memberId.

Parameters

memberId `string` (required) Unique identifier for the member

Endpoint

DELETE /api/partners/members/{memberId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/partners/members/{memberId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a member by memberId

Updates an existing member record using the memberId.

Parameters

memberId `string` (required) Unique identifier for the member

Request Body

Endpoint

PUT /api/partners/members/{memberId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/partners/members/{memberId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Get the status of a member-sync operation

Returns the current state of an asynchronous member create/delete operation that was started via POST /api/partners/members or DELETE /api/partners/members/{memberId}. The frontend polls this endpoint to replace the legacy list-polling + name-matching flow. NOTE Row-level partnerId/facilityId scoping is mandated by the multi-tenant isolation rules but deferred to a Phase 3a.1 hardening PR — operationIds are 128-bit UUIDs and the route is already gated by `external-integrations` module access. Anyone with a valid operationId and admin module access can query its status.

Parameters

operationId `string` (required) UUID returned from POST/DELETE

Endpoint

GET /api/partners/members/operations/{operationId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/partners/members/operations/{operationId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update members for a facility

Accepts an array of member objects and forwards them to the Partner API for processing. Maximum of 25 members per request.

Request Body

Endpoint

POST /api/partners/members

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/members \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Create or update membership plans for a facility

Accepts an array of membership plan objects and forwards them to the Partner API for processing. Maximum of 25 membership plans per request.

Request Body

Endpoint

POST /api/partners/membership-plans

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/partners/membership-plans \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Creates a new role

Parameters

body `string` (required) Role object

Endpoint

POST /api/roles

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/roles \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all roles

Endpoint

GET /api/roles

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/roles \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deletes an role by ID

Endpoint

DELETE /api/roles/{roleId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/roles/{roleId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates an role by ID

Parameters

body `string` (required) Role object

Endpoint

PUT /api/roles/{roleId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/roles/{roleId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a new additional line item for the saas billing invoice

Parameters

organisationId `string` (optional) The organisation ID to create the additional line item for body `string` (optional) Body of the request

Endpoint

POST /api/saas-billing/additional-line-items

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/saas-billing/additional-line-items \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of additional line items for the saas billing invoice

Parameters

organisationId `string` (required) The organisation ID

Endpoint

GET /api/saas-billing/additional-line-items

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/additional-line-items \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of additional line items for club's saas billing invoice

Endpoint

GET /api/clubs/{clubId}/saas-billing/additional-line-items

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubId}/saas-billing/additional-line-items \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates an additional line item for the saas billing invoice

Parameters

itemId `string` (required) The ID of the additional line item to update body `string` (required) The body of the request

Endpoint

PUT /api/saas-billing/additional-line-items/{itemId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/saas-billing/additional-line-items/{itemId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Combined Cloud Agent hourly rates for Your Rates

Returns offered Cloud Agent sizes with a single combined hourly price (hosting + software). The split is not included. usedPlans are SKUs this facility ran in the last 30 days.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/cloud-agent-rates

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/cloud-agent-rates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete imported monthly report

Parameters

club `string` (optional) Club ID reportId `string` (optional) Report ID

Endpoint

DELETE /api/saas-billing/extended-access/monthly-usage-report/{reportId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/{reportId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the latest CCTV storage report for a club

Returns the most recent daily CCTV storage snapshot for the club from stored billing logs (up to the last 31 days). Includes totalStorage, date, and storage-related charges.

Parameters

club `string` (required) Club ID

Endpoint

GET /api/saas-billing/extended-access/latest-cctv-storage-report/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/latest-cctv-storage-report/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a pdf invoice for the club for the given period.

Parameters

club `string` (optional) Club ID month `string` (optional) month of the report in number format. 1 = January, 2 = February etc. year `string` (optional) year of the report in number format. e.g. 2021

Endpoint

GET /api/saas-billing/extended-access/monthly-usage-report/:club/invoice

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/:club/invoice \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bundle of platform invoice PDFs for the selected usage months, as a ZIP. Bulk counterpart of the single .../invoice endpoint — powers the multi-select download on the Billing & Cost Management applet's Invoices & Receipts tab.

Parameters

club `string` (optional) Club ID months `string` (optional) Comma-separated usage/report months in YYYY-MM format (max 24)

Endpoint

GET /api/saas-billing/extended-access/monthly-usage-report/{club}/invoices.zip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/{club}/invoices.zip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns monthly usage reports for multiple usage months in one call. Powers the Cost History chart and month-over-month deltas in the Billing & Cost Management applet. Months with no usage yet return report: null (matching the single-month endpoint's 404 → $0 UI).

Parameters

club `string` (optional) Club ID months `string` (optional) Comma-separated usage months in YYYY-MM format (max 12)

Endpoint

GET /api/saas-billing/extended-access/monthly-usage-report/{club}/batch

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/{club}/batch \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Import monthly reports for the club.

Parameters

club `string` (optional) Club ID

Endpoint

PUT /api/saas-billing/extended-access/usage-report/:club

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/saas-billing/extended-access/usage-report/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a CSV report of the CCTV Usage for the last 30 days for all clubs.

Endpoint

GET /api/saas-billing/extended-access/usage-report/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/usage-report/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all the daily reports of the month for the club.

Parameters

club `string` (optional) Club ID month `string` (optional) month of the report in number format. 1 = January, 2 = February etc. year `string` (optional) year of the report in number format. e.g. 2021

Endpoint

GET /api/saas-billing/extended-access/monthly-usage-report/{club}/daily-reports

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/{club}/daily-reports \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of imported monthly reports for the admin

Parameters

organisationId `string` (required) Organisation ID

Endpoint

GET /api/saas-billing/extended-access/usage-report/imported

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/usage-report/imported \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a CSV report of the CCTV Usage for the last 30 days for all clubs.

Parameters

club `string` (optional) Club ID month `string` (optional) month of the report in number format. 1 = January, 2 = February etc. year `string` (optional) year of the report in number format. e.g. 2021

Endpoint

GET /api/saas-billing/extended-access/monthly-usage-report/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/monthly-usage-report/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the periodical usage report for the club.

Parameters

club `string` (optional) Club ID periodStart `string` (optional) Start of the period in the format of YYYY-MM-DD periodEnd `string` (optional) End of the period in the format of YYYY-MM-DD

Endpoint

GET /api/saas-billing/extended-access/periodical-usage-report/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/extended-access/periodical-usage-report/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bundle of billing-document PDFs as a single ZIP, mixing document types: platform invoices (by usage month), SaaS-wallet top-up receipts, and Model Router top-up receipts. Bulk counterpart of the per-type invoices.zip / receipts.zip endpoints for the consolidated Invoices & Receipts tab. Every requested month/id must resolve to a document the facility owns — any bad value fails the whole bundle.

Parameters

clubID `string` (required) invoiceMonths `string` (optional) Comma-separated usage months in YYYY-MM format walletIds `string` (optional) Comma-separated SaaS-wallet top-up transaction ids aiIds `string` (optional) Comma-separated Model Router top-up transaction ids

Endpoint

GET /api/clubs/{clubID}/saas-billing/documents.zip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/documents.zip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add a note to a monthly record

Parameters

recordID `string` (optional) The ID of the record to get note `string` (optional) The note to add to the record

Endpoint

POST /api/saas-billing/monthly-records/{recordID}/notes

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/saas-billing/monthly-records/{recordID}/notes \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of saas billing monthly records

Parameters

club `string` (optional) The ID of the club to get month `string` (optional) The billing month in YYYY-MM format

Endpoint

GET /api/saas-billing/monthly-records/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/monthly-records/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of saas billing monthly records that have failed or require 3d secure

Parameters

clubID `string` (optional) The ID of the club to get the failed monthly records for

Endpoint

GET /api/clubs/:clubID/saas-billing/flagged

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/:clubID/saas-billing/flagged \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns ALL saas billing monthly records (the invoice ledger) for a club, newest billing month first. Club-scoped counterpart of the admin-only paginate-monthly-records endpoint — powers the customer "Invoices & Receipts" tab in the Billing & Cost Management applet.

Parameters

clubID `string` (optional) The ID of the club to list the monthly records for

Endpoint

GET /api/clubs/{clubID}/saas-billing/monthly-records

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/monthly-records \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of saas billing monthly records

Parameters

organisationId `string` (optional) Organisation ID month `string` (optional) Month in MM format. year `string` (optional) Year in YYYY format. filters `string` (optional) Datatable created query string filters. order `string` (optional) Datatable created query string.

Endpoint

GET /api/saas-billing/monthly-records

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/monthly-records \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retry failed payments for a club

Parameters

clubID `string` (optional) The ID of the club to get the failed monthly records for

Endpoint

PUT /api/clubs/:clubID/saas-billing/retry-failed-payments

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/:clubID/saas-billing/retry-failed-payments \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a monthly record

Parameters

recordID `string` (optional) The ID of the record to get status `string` (optional) The status to update the record to

Endpoint

PUT /api/saas-billing/monthly-records/{recordID}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/saas-billing/monthly-records/{recordID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Checks if payments have succeeded and updates the status of the record

Parameters

clubID `string` (optional) recordID `string` (optional) The ID of the record to get

Endpoint

PUT /api/clubs/{clubID}/saas-billing/monthly-records/{recordID}/validate

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/monthly-records/{recordID}/validate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add a payment method for a club.

Parameters

clubID `string` (optional)

Endpoint

POST /api/clubs/{clubID}/saas-billing/payment-settings/payment-methods

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/payment-methods \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Syncs the payment methods for a club with Stripe.

Parameters

clubID `string` (optional)

Endpoint

PUT /api/clubs/{clubID}/saas-billing/payment-settings/payment-methods

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/payment-methods \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns the facility's spend budget plus computed MTD/forecast.

Parameters

clubID `string` (optional)

Endpoint

GET /api/clubs/{clubID}/saas-billing/budget

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/budget \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create/update/clear the facility spend budget.

Parameters

clubID `string` (optional) body `object` (optional)

Endpoint

PUT /api/clubs/{clubID}/saas-billing/budget

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/budget \
  -H "x-api-key: YOUR_API_KEY"

Delete a payment method from the club's payment settings.

Parameters

clubID `string` (optional) paymentMethodID `string` (optional)

Endpoint

DELETE /api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{paymentMethodID}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{paymentMethodID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the payment settings for a club.

Parameters

clubID `string` (optional)

Endpoint

GET /api/clubs/{clubID}/saas-billing/payment-settings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a club's payment settings.

Parameters

clubID `string` (optional) lockedOut `boolean` (optional) Whether the club will be locked out of the system. pauseBilling `boolean` (optional) Whether automatic billing for the club will be paused. customerID `string` (optional) Adding this will update the stripe customer ID for the club. deleteSourceID `string` (optional) Wether to delete the source customer from stripe.

Endpoint

PUT /api/clubs/{clubID}/saas-billing/payment-settings

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the earliest billed month for all clubs.

Parameters

clubID `string` (optional)

Endpoint

GET /api/saas-billing/payment-settings/earliest-billed-month

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/payment-settings/earliest-billed-month \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List the accounts that can clear a billing lockout for a club, tiered: users holding the billing module first, organisation admins only as a fallback when nobody does. Platform super admins are never returned.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/lockout-contacts

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/lockout-contacts \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Paginate through all clubs in the system and return the customer IDs for each club.

Parameters

clubID `string` (optional) organisationId `string` (optional) Organisation ID

Endpoint

GET /api/saas-billing/payment-settings/customer-ids

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/payment-settings/customer-ids \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Set the primary payment method for a club.

Parameters

clubID `string` (optional)

Endpoint

PUT /api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{paymentMethodID}/primary

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{paymentMethodID}/primary \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the billing profile for a club.

Parameters

clubID `string` (optional) invoiceEntity `string` (optional) billingContacts `string` (optional) List of uuids of kyc contacts ccEmails `string` (optional) List of emails to cc on invoices

Endpoint

PUT /api/clubs/{clubID}/saas-billing/payment-settings/billing-profile

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/billing-profile \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a payment method for a club.

Parameters

clubID `string` (optional) cardID `string` (optional)

Endpoint

PUT /api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{cardID}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/payment-settings/payment-methods/{cardID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Soft-delete a rate block. Blocks derived from it are detached (they keep their current values).

Parameters

configId `string` (optional) The configId of the config to delete.

Endpoint

DELETE /api/admin/saas-billing/charges-config/{configId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/saas-billing/charges-config/{configId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a per-facility breakdown of all applicable product charges and additional line items for CSV export. Resolves the global/region/facility override hierarchy for every facility the user has access to.

Parameters

organisationId `string` (required) Organisation ID for ACL

Endpoint

GET /api/saas-billing/charges-config/export

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/charges-config/export \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns charges config of specific target

Parameters

clubId `string` (optional) The club ID of the club to get the charges config for

Endpoint

GET /api/saas-billing/charges-config/{clubId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/saas-billing/charges-config/{clubId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns list of all charges config.

Parameters

organisationId `string` (required)

Endpoint

GET /api/admin/saas-billing/charges-config

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/saas-billing/charges-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update charges config of an organisation

Parameters

organisationId `string` (optional) The organisation ID to update the charges config for body `object` (optional) Body of the request

Endpoint

PUT /api/admin/saas-billing/charges-config

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/saas-billing/charges-config \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Organisation billing summary for this facility's org — effective payer scope, any scheduled consolidation change, and whether the caller may manage the consolidation toggle (super-admin only for now — see the org-admin applet TODO in this file).

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/org/summary

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/org/summary \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable/disable consolidated billing for this facility's ORGANISATION. Platform super-admins only (moving to the org-admin applet — see the TODO in this file). The change is always scheduled for the next month boundary so wallets/statements never switch payer mid-month.

Parameters

clubID `string` (required) body `string` (optional) { enabled: boolean }

Endpoint

PUT /api/clubs/{clubID}/saas-billing/org/consolidation

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/org/consolidation \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Consolidated organisation monthly records (statements) with the per-facility breakdown, newest first. Empty until the org's first consolidated month settles.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/org/monthly-records

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/org/monthly-records \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Prepaid wallet summary — balance, month-to-date usage debits, auto-top-up config, billing method.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/wallet

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Wallet ledger, newest first. Org-scoped wallets include all facilities' rows (each carries its originating clubID).

Parameters

clubID `string` (required) limit `string` (optional) types `string` (optional) comma-separated transaction types from `string` (optional) to `string` (optional) cursor `string` (optional) nextCursor from a previous page

Endpoint

GET /api/clubs/{clubID}/saas-billing/wallet/transactions

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/transactions \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Branded PDF receipt for a single wallet transaction (top-ups and credits).

Parameters

clubID `string` (required) txId `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/wallet/transactions/{txId}/receipt.pdf

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/transactions/{txId}/receipt.pdf \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Bundle of branded PDF receipts for the selected wallet top-up transactions, as a ZIP. Every id must be a top-up (card or invoice) belonging to this facility's wallet — usage debits and adjustments have no receipts and are rejected.

Parameters

clubID `string` (required) ids `string` (required) Comma-separated transaction ids (max 50)

Endpoint

GET /api/clubs/{clubID}/saas-billing/wallet/transactions/receipts.zip

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/transactions/receipts.zip \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Charge a stored SaaS-billing card to add prepaid balance. Returns requires_action + clientSecret when 3DS is needed.

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

POST /api/clubs/{clubID}/saas-billing/wallet/topup

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/topup \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Finalise a wallet top-up after the applet completes 3DS authentication. Idempotent.

Parameters

clubID `string` (required)

Endpoint

POST /api/clubs/{clubID}/saas-billing/wallet/topup/confirm

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/topup/confirm \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update the facility's auto-top-up rule (stored on its billing-profile override row).

Parameters

clubID `string` (required) body `object` (optional)

Endpoint

PATCH /api/clubs/{clubID}/saas-billing/wallet/auto-topup

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/auto-topup \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Top-up invoices for this facility's wallet (invoice payment method), newest first.

Parameters

clubID `string` (required)

Endpoint

GET /api/clubs/{clubID}/saas-billing/wallet/invoices

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/invoices \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Request a pay-by-reference top-up invoice (invoice payment method only). At most one pending invoice per wallet — a second request returns the existing one with alreadyPending=true.

Parameters

clubID `string` (required) body `string` (optional) { amountCents: number }

Endpoint

POST /api/clubs/{clubID}/saas-billing/wallet/topup-invoice

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/clubs/{clubID}/saas-billing/wallet/topup-invoice \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deletes a secure upload record

Parameters

type `string` (required) key `string` (required) permanent `string` (optional)

Endpoint

DELETE /api/admin/secure-upload/{type}/{key}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/secure-upload/{type}/{key} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns object information

Parameters

type `string` (required) key `string` (required)

Endpoint

GET /api/admin/secure-upload/{type}/{key}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/{type}/{key} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a signed URL for uploading a file to S3

Parameters

fileName `string` (required) The name of the file to be uploaded including the extension public `string` (optional) Whether the file should be uploaded to the public bucket

Endpoint

GET /api/admin/secure-upload/token

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/token \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of files uploaded using the old php uploader that now reside in S3

Endpoint

GET /api/admin/secure-upload/legacy-files

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/legacy-files \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of files uploaded to S3

Endpoint

GET /api/admin/secure-upload/files

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/files \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates/updates a secure upload record

Parameters

body `object` (required)

Endpoint

POST /api/admin/secure-upload/files

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/secure-upload/files \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Proxy a file from S3

Parameters

type `string` (optional) The type of file to retrieve key `string` (optional) The key of the file to retrieve

Endpoint

GET /api/admin/secure-upload/private/{type}/{key}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/private/{type}/{key} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Proxy a file from S3

Parameters

type `string` (optional) The type of file to retrieve key `string` (optional) The key of the file to retrieve

Endpoint

GET /api/admin/secure-upload/public/{type}/{key}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/secure-upload/public/{type}/{key} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Converts pending videos and audio into small chunks and places them in S3

Endpoint

POST /api/admin/media-convert

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/admin/media-convert \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates the progress of a file conversions

Endpoint

PUT /api/admin/media-convert/progress

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/media-convert/progress \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of orders for the facility.

Parameters

facilityID `string` (optional)

Endpoint

GET /api/store/facilities/:facilityID/orders

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/store/facilities/:facilityID/orders \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of products available to the club.

Parameters

clubID `string` (required) search `string` (optional) limit `string` (optional) page `string` (optional) The page number for pagination (starts at 1).

Endpoint

GET /api/store/clubs/{clubID}/products

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/store/clubs/{clubID}/products \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates club info in expresscart store v2.

Parameters

clubID `string` (required)

Endpoint

PUT /api/admin/store/clubs/{clubID}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/admin/store/clubs/{clubID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns all ticket history based on the Club ID

Parameters

club `string` (required) Internal ID of the club that you wish to access.

Endpoint

GET /api/ticketing/clubtickets/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ticketing/clubtickets/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets the departments

Endpoint

GET /api/ticketing/departments

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ticketing/departments \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets the details of a single ticket

Parameters

user `string` (required) email of the user. ticketNumber `string` (required) 6-digit ID of the ticket you wish to access. club `string` (required) the selected club id.

Endpoint

GET /api/ticketing/ticket-details/:ticketNumber/:club

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ticketing/ticket-details/:ticketNumber/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets the topics

Endpoint

GET /api/ticketing/topics

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ticketing/topics \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Gets all the tickets created by the current logged in user - Note this is set from the headers provided by our google SSO service.

Parameters

user `string` (required) Email of the user that is currently logged-in

Endpoint

GET /api/ticketing/usertickets

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/ticketing/usertickets \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a new ticket

Parameters

club `string` (required) the selected club id.

Endpoint

POST /api/ticketing/clubticket/:club

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ticketing/clubticket/:club \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a new ticket

Parameters

subject `string` (required) Subject of the ticket. message `string` (required) Full message of the ticket.

Endpoint

POST /api/ticketing/userticket

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ticketing/userticket \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a reply to an existing ticket

Parameters

subject `string` (required) Subject of the ticket. message `string` (required) Full message of the ticket.

Endpoint

POST /api/ticketing/user-reply

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/ticketing/user-reply \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Retrieves a user's preferences

Endpoint

GET /api/user-preferences

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/user-preferences \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates a user's preferences

Parameters

body `string` (required)

Endpoint

PUT /api/user-preferences

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/user-preferences \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Change user password

Changes the user's password. Requires OTP verification if user has a phone number, or requires phone number to be added if not present.

Request Body

Endpoint

POST /api/user/change-password

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/change-password \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Check user's 2FA status

Returns whether 2FA is enabled for the user and if any of their roles force 2FA

Endpoint

GET /api/user/check-2fa-status

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/user/check-2fa-status \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List the organisations, facilities, and regions the user has access to for a specific module.

Parameters

moduleId `string` (required)

Endpoint

POST /api/user/me/modules/{moduleId}/org-access

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/me/modules/{moduleId}/org-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Creates a 'Linking Request' from an end user, requesting to 'Join' a club.

Parameters

body `string` (required) Json Object of the new club to add to the system.

Endpoint

POST /api/user/linkclub

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/linkclub \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Lists all clubs authorised to the user.

Endpoint

GET /api/user/listauthorised

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/user/listauthorised \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Send dual-channel OTP (email + SMS)

Sends OTP codes to both the user's email address and a specified phone number. Used for high-security operations like first-time phone number verification. This endpoint only sends OTPs and does not modify any user data.

Request Body

Endpoint

POST /api/user/send-dual-otp

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/send-dual-otp \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Send OTP to phone number or email

Sends an OTP code to the user's phone number (SMS) or email address for verification

Request Body

Endpoint

POST /api/user/send-otp

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/send-otp \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Check if user has valid sensitive page access

Returns whether the user has a valid OTP-verified session for accessing sensitive pages

Endpoint

GET /api/user/sensitive-page-access

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/user/sensitive-page-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Verify OTP and grant sensitive page access

Verifies the OTP code and grants 1-hour access to sensitive pages if valid

Request Body

Endpoint

POST /api/user/sensitive-page-access/verify

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/sensitive-page-access/verify \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Revoke sensitive page access (logout from sensitive pages)

Revokes the user's current sensitive page access session

Endpoint

POST /api/user/sensitive-page-access/revoke

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/sensitive-page-access/revoke \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable or disable 2FA

Enables or disables two-factor authentication for the user. Requires phone number and OTP verification.

Request Body

Endpoint

POST /api/user/toggle-2fa

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/user/toggle-2fa \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Update user's own profile

Allows a user to update their own profile information (first name, last name, phone number). When adding a phone number for the first time, dual-channel OTP verification is required (both email and SMS codes). When changing an existing phone number, only email OTP is required.

Request Body

Endpoint

PATCH /api/user/update-profile

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/user/update-profile \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Retrieve an icon based on the url.

Endpoint

GET /api/website-icon

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/website-icon \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List password vault entry templates

Parameters

organisationId `string` (optional) Organisation context for module access checks

Endpoint

GET /api/vault/templates

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/vault/templates \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List visible password vault entries

Parameters

organisationId `string` (required) scope `string` (optional)

Endpoint

GET /api/vault/entries

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/vault/entries \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a password vault entry

Endpoint

POST /api/vault/entries

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/vault/entries \
  -H "x-api-key: YOUR_API_KEY"

Get a password vault entry without revealed secret values

Parameters

entryId `string` (required) organisationId `string` (required)

Endpoint

GET /api/vault/entries/{entryId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/vault/entries/{entryId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Update a password vault entry

Endpoint

PUT /api/vault/entries/{entryId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/vault/entries/{entryId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a password vault entry

Endpoint

DELETE /api/vault/entries/{entryId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/vault/entries/{entryId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Reveal selected concealed or secret fields

Endpoint

POST /api/vault/entries/{entryId}/reveal

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/vault/entries/{entryId}/reveal \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List password vault folder summaries

Endpoint

GET /api/vault/folders

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/vault/folders \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List entries with authenticator codes

Endpoint

GET /api/vault/authenticator

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/vault/authenticator \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List registered workflow node types

Endpoint

GET /api/workflow-engine/node-types

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/node-types \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get the facility-hours projection used by workflow blocks

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/facility-hours/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/facility-hours/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Preview the facility-branded workflow email sender

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/email-branding/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/email-branding/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List workflow event trigger definitions (global admin)

Endpoint

GET /api/workflow-engine/trigger-catalog

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/trigger-catalog \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update a workflow event trigger definition (global admin)

Parameters

triggerType `string` (required)

Endpoint

PUT /api/workflow-engine/trigger-catalog/{triggerType}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/workflow-engine/trigger-catalog/{triggerType} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Deactivate a workflow event trigger definition (global admin)

Parameters

triggerType `string` (required)

Endpoint

DELETE /api/workflow-engine/trigger-catalog/{triggerType}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/workflow-engine/trigger-catalog/{triggerType} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List facility resources for trigger configuration

Parameters

facilityId `string` (required) resourceType `string` (required)

Endpoint

GET /api/workflow-engine/resources/{facilityId}/{resourceType}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/resources/{facilityId}/{resourceType} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List workflows for a facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/workflows/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a draft workflow from a non-empty graph

The editor keeps a new workflow local until it has at least one block, so the first save creates it with its graph in one call. A body with no `nodes` is rejected rather than stored.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List credentials a facility's workflows may use

Returns the facility's own credentials plus any shared at its brand or organisation. Secrets are never returned; `hasValue` reports only that one is stored.

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/credentials/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/credentials/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a workflow credential

The scope level comes from `scopeType`; the brand and organisation ids are resolved from the facility rather than accepted from the caller.

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/credentials/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/credentials/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Facility-wide workflow settings (failure-notification recipients)

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/facility-settings/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/facility-settings/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Store facility-wide failure notifications recipients

Parameters

facilityId `string` (required)

Request Body

Endpoint

PUT /api/workflow-engine/facility-settings/{facilityId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/workflow-engine/facility-settings/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Replace a workflow credential

An empty `secret` keeps the stored one, so a credential can be renamed without re-entering it. There is no way to read a secret back.

Parameters

facilityId `string` (required) credentialId `string` (required)

Endpoint

PUT /api/workflow-engine/credentials/{facilityId}/{credentialId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/workflow-engine/credentials/{facilityId}/{credentialId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a workflow credential

Nodes referencing it fail closed on the next call, including in already published workflows, because a snapshot stores only the reference.

Parameters

facilityId `string` (required) credentialId `string` (required)

Endpoint

DELETE /api/workflow-engine/credentials/{facilityId}/{credentialId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/workflow-engine/credentials/{facilityId}/{credentialId} \
  -H "x-api-key: YOUR_API_KEY"

Get a workflow trigger's webhook URL

Parameters

facilityId `string` (required) workflowId `string` (required) nodeId `string` (required)

Endpoint

GET /api/workflow-engine/workflows/{facilityId}/{workflowId}/nodes/{nodeId}/webhook

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/nodes/{nodeId}/webhook \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Rotate a workflow trigger's webhook URL

Immediately invalidates the previous URL.

Parameters

facilityId `string` (required) workflowId `string` (required) nodeId `string` (required)

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/nodes/{nodeId}/webhook/rotate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/nodes/{nodeId}/webhook/rotate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get a workflow by id

Parameters

facilityId `string` (required) workflowId `string` (required)

Endpoint

GET /api/workflow-engine/workflows/{facilityId}/{workflowId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create or update a draft workflow

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

PUT /api/workflow-engine/workflows/{facilityId}/{workflowId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Update workflow name and/or description

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

PATCH /api/workflow-engine/workflows/{facilityId}/{workflowId}

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Delete a workflow and its versions

Parameters

facilityId `string` (required) workflowId `string` (required)

Endpoint

DELETE /api/workflow-engine/workflows/{facilityId}/{workflowId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Duplicate a workflow into a new inactive draft

Parameters

facilityId `string` (required) workflowId `string` (required)

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/duplicate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/duplicate \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Publish the current draft (immutable version snapshot)

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/publish

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/publish \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Reset the draft to the last published version

Parameters

facilityId `string` (required) workflowId `string` (required)

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/discard

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/discard \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Enable or disable a workflow

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

PATCH /api/workflow-engine/workflows/{facilityId}/{workflowId}/active

Example Request

curl -X PATCH https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/active \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Generate or revise a workflow graph with AI

Parameters

facilityId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/generate/{facilityId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/generate/{facilityId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List models an Agent node can run on for this facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/agent-models/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/agent-models/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List MCP tools an Agent node may attach for this facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/agent-tools/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/agent-tools/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search this facility's persisted Agent conversations (Conversation key bindings)

Parameters

facilityId `string` (required) deviceId `string` (optional) Restrict to one Agent device's conversations (the node's configured deviceId) q `string` (optional) Case-insensitive substring match on the Conversation key, session id, or device name limit `integer` (optional) offset `integer` (optional)

Endpoint

GET /api/workflow-engine/agent-conversations/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/agent-conversations/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search the conversations held on the facility's Agent device itself

Lists the device's own sessions (the Agent UI sidebar conversations) so a workflow can continue an existing conversation with its context. The device owns the history; when the facility has several devices, `deviceId` picks which one (the node's configured device). Unreachable device → 502.

Parameters

facilityId `string` (required) deviceId `string` (optional) The node's configured Agent device; omit to resolve the facility's single device q `string` (optional) Case-insensitive substring match on the session title or id limit `integer` (optional) offset `integer` (optional)

Endpoint

GET /api/workflow-engine/agent-device-sessions/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/agent-device-sessions/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search the boards on the facility's Agent device kanban

Feeds the Agent: Kanban block's Board ID picker. Case-insensitive substring match on the board name or slug; `current` is the device's active board slug so the task picker can default its scope. When the facility has several devices, `deviceId` picks which one. Unreachable device → 502.

Parameters

facilityId `string` (required) deviceId `string` (optional) The node's configured Agent device; omit to resolve the facility's single device q `string` (optional) Case-insensitive substring match on the board name or slug limit `integer` (optional) offset `integer` (optional)

Endpoint

GET /api/workflow-engine/kanban-boards/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/kanban-boards/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Search one board's tasks on the facility's Agent device kanban

Feeds the Agent: Kanban block's Task ID picker. Case-insensitive substring match on the task id, title, or body; tasks live per board (the device has no cross-board search), so `board` scopes the fetch — omit it for the device's active board. Unreachable device → 502.

Parameters

facilityId `string` (required) deviceId `string` (optional) The node's configured Agent device; omit to resolve the facility's single device board `string` (optional) The board slug to list; omit for the device's active board q `string` (optional) Case-insensitive substring match on the task id, title, or body limit `integer` (optional) offset `integer` (optional)

Endpoint

GET /api/workflow-engine/kanban-tasks/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/kanban-tasks/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List curated workflow templates, filtered for this facility

Parameters

facilityId `string` (required)

Endpoint

GET /api/workflow-engine/templates/{facilityId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/templates/{facilityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Instantiate a template into a graph fragment for the open draft

Parameters

facilityId `string` (required) templateId `string` (required)

Endpoint

POST /api/workflow-engine/templates/{facilityId}/{templateId}

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/templates/{facilityId}/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Scope picker context for the template admin page (admin tiers)

Endpoint

GET /api/workflow-engine/template-admin/context

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/template-admin/context \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

List templates the caller may administer, with permission flags

Endpoint

GET /api/workflow-engine/template-admin

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/template-admin \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a template (admin tiers)

Request Body

Endpoint

POST /api/workflow-engine/template-admin

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/template-admin \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Template detail incl. graph, for the admin editor

Endpoint

GET /api/workflow-engine/template-admin/{templateId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/template-admin/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Replace a template (owner org or global admin)

Endpoint

PUT /api/workflow-engine/template-admin/{templateId}

Example Request

curl -X PUT https://portal.hub.gymsystems.co/api/workflow-engine/template-admin/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Soft-delete a template (owner org or global admin)

Endpoint

DELETE /api/workflow-engine/template-admin/{templateId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/workflow-engine/template-admin/{templateId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Duplicate a visible template into a target scope the caller may use

Request Body

Endpoint

POST /api/workflow-engine/template-admin/{templateId}/duplicate

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/template-admin/{templateId}/duplicate \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Run a workflow's published graph from a manual trigger

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/run

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/run \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Test the saved draft without publishing it

Executes the current draft graph and records the result with `mode: test` and no `versionId`. Publishing, the live flag, and `publishedVersionId` are never touched. Side effects are simulated by default; `sideEffects: live` additionally requires `confirmLiveSideEffects: true`.

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/test

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/test \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Test one allowlisted workflow node

Executes one independently testable node from the saved draft. Variable values may be supplied from recorded run steps. Mutating HTTP methods require explicit confirmation.

Parameters

facilityId `string` (required) workflowId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/test-node

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/test-node \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

List recent runs for a workflow

Parameters

facilityId `string` (required) workflowId `string` (required)

Endpoint

GET /api/workflow-engine/workflows/{facilityId}/{workflowId}/runs

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/runs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Read one run (status + ordered steps)

Parameters

facilityId `string` (required) workflowId `string` (required) executionId `string` (required)

Endpoint

GET /api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Cancel the pending Delay a waiting run is sitting on

Parameters

facilityId `string` (required) workflowId `string` (required) executionId `string` (required)

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId}/cancel

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId}/cancel \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Replay a finished run from its recorded trigger payload

`mode: published` re-executes the exact version the original run was pinned to, with real side effects. `mode: draft-test` re-executes the current draft as a simulated test. A run whose trigger payload was truncated on write cannot be replayed.

Parameters

facilityId `string` (required) workflowId `string` (required) executionId `string` (required)

Request Body

Endpoint

POST /api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId}/retry

Example Request

curl -X POST https://portal.hub.gymsystems.co/api/workflow-engine/workflows/{facilityId}/{workflowId}/runs/{executionId}/retry \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Indexed lookup of workflows containing a node type

Parameters

nodeType `string` (required) facilityId `string` (optional) organisationId `string` (optional)

Endpoint

GET /api/workflow-engine/master-view/{nodeType}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/workflow-engine/master-view/{nodeType} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Create a new location entity on yext.

Parameters

facilityId `string` (optional) The facility ID to create the location for.

Endpoint

GET /api/admin/yext/location

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/yext/location \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Delete a location entity on yext.

Parameters

entityId `string` (optional) facilityId `string` (optional) The facility ID to delete the location for.

Endpoint

DELETE /api/admin/yext/location/{entityId}

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/api/admin/yext/location/{entityId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Updates an existing location entity on yext.

Parameters

id `string` (required) Location id facilityId `string` (optional) The facility ID to update the location for.

Endpoint

GET /api/admin/yext/location/{id}

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/yext/location/{id} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

list all listings given a club.

Parameters

clubId `string` (required)

Endpoint

GET /api/admin/club/{clubId}/yext/listings

Example Request

curl -X GET https://portal.hub.gymsystems.co/api/admin/club/{clubId}/yext/listings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

White-label OAuth redirect proxy (Connected Apps)

Public unauthenticated 302 that forwards an OAuth provider callback to the upstream tool platform's auth callback, preserving the query string. Lets PH-owned OAuth apps register a performancehub.co redirect URI so the upstream vendor's domain never appears in the address bar (needed for the future custom-OAuth-apps project; harmless under managed auth).

Endpoint

GET /guest/connected-apps/oauth-callback

Example Request

curl -X GET https://portal.hub.gymsystems.co/guest/connected-apps/oauth-callback \
  -H "x-api-key: YOUR_API_KEY"

Connect-chain finish page (Connected Apps)

Lightweight "you can close this window" landing for the OAuth tab a connect chain ran in. Posts the result (connected suite/toolkit + new account ids, or the failed toolkit) back to the marketplace tab via same-origin window.opener.postMessage; when the opener was severed it falls back to a deep link into the ph-ai-agent applet that reproduces the in-app landing. Purely informational — holds no secrets and performs no writes.

Parameters

connected `string` (optional) Suite id or toolkit slug that finished connecting (success case). accounts `string` (optional) Comma-separated connected account ids the chain created. connectError `string` (optional) Toolkit slug whose step failed (failure case).

Endpoint

GET /guest/connected-apps/finish

Example Request

curl -X GET https://portal.hub.gymsystems.co/guest/connected-apps/finish \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Suite connect chaining callback (Connected Apps)

OAuth-callback hop for the one-click suite connect flow. The signed state JWT (HS256, 30 min TTL) encodes { clubID, deviceId, suite, toolkits, step, caids } — the accounts connect to that one agent device, and caids accumulates the account ids each hop created (the final applet redirect carries them so the marketplace can offer to label the new accounts). Marks the step's toolkit connected, then 302s into the next toolkit's Connect Link — or to the ph-ai-agent applet page (deep-linked to the agent) when the suite is finished. Single-toolkit connects run through the same handler with a one-toolkit suite.

Parameters

state `string` (required) Signed connect-chain state JWT.

Endpoint

GET /guest/connected-apps/connect-next

Example Request

curl -X GET https://portal.hub.gymsystems.co/guest/connected-apps/connect-next \
  -H "x-api-key: YOUR_API_KEY"

Trigger password setup email

Validates the signed link from a welcome email, triggers a password reset email, and shows a confirmation page. No authentication required.

Parameters

email `string` (required) User email address sig `string` (required) HMAC signature for the email

Endpoint

GET /guest/setup-password

Example Request

curl -X GET https://portal.hub.gymsystems.co/guest/setup-password \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns metadata for the selected Club's ID.

Parameters

clubID `string` (required) Internal ID of the club that you wish to return data on.

Endpoint

GET /internal/clubs/club-data/{clubID}

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/clubs/club-data/{clubID} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns data for the Facility

Parameters

facilityId `string` (optional) The ID of the facility to retrieve data for. slug `string` (optional) The slug of the facility to retrieve data for.

Endpoint

GET /internal/facilities

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/facilities \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of all clubs in the system.

Endpoint

GET /internal/clubs/list-clubs

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/clubs/list-clubs \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns an array of user emails that have permission to a club

Parameters

club `string` (optional) Internal ID of the club that you wish to access.

Endpoint

GET /internal/clubs/list-user-access/{club}

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/clubs/list-user-access/{club} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of all users and what clubs they have permission to access.

Endpoint

GET /internal/clubs/list-user-access

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/clubs/list-user-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Notifies the requester that a device-replacement restore reached a terminal state. Called by universal-api's backup restore-status handler; the outcome is read from the registration's restoreRequest, not from the request body.

Parameters

body `object` (optional)

Endpoint

POST /internal/devices/ph-ai-agent/restore-complete

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/devices/ph-ai-agent/restore-complete \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns brand settings for the selected facility.

Parameters

facilityId `string` (required) Internal ID of the facility that you wish to return data on.

Endpoint

GET /internal/facilities/{facilityId}/brand-settings

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/facilities/{facilityId}/brand-settings \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Internal API to delete article embeddings from vector store

Request Body

Endpoint

DELETE /internal/llm/delete-article

Example Request

curl -X DELETE https://portal.hub.gymsystems.co/internal/llm/delete-article \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Internal API to upsert article embeddings into vector database

Handles article embedding based on current state: - If article is unpublished OR private: deletes embeddings - If article is published AND public: re-embeds with full content Always requires full article body.

Request Body

Endpoint

POST /internal/llm/upsert-embeddings

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/llm/upsert-embeddings \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Return organisation data

Parameters

orgId `string` (optional) ID of the organisation you wish to retrieve.

Endpoint

GET /internal/organisations/{orgId}

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/organisations/{orgId} \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Returns a list of organisations.

Parameters

orgId `string` (optional) ID of the organisation you wish to retrieve.

Endpoint

GET /internal/organisations

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/organisations \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get simplified list of roles for an organisation

Returns a simplified list of roles available to an organisation without user access filtering

Parameters

organisationId `string` (required) The organisation ID to get roles for

Endpoint

GET /internal/organisations/{organisationId}/roles

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/organisations/{organisationId}/roles \
  -H "x-api-key: YOUR_API_KEY"

Response

[]

Returns the data of user preferences.

Endpoint

GET /user-preferences/get-user-preferences

Example Request

curl -X GET https://portal.hub.gymsystems.co/user-preferences/get-user-preferences \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Return user data and their access to modules

Parameters

email `string` (required) Email of the user you wish to check access for. moduleId `string` (required) Internal ID of the module that you wish to check access for (can be multiple).

Endpoint

GET /internal/clubs/get-user-access

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/clubs/get-user-access \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Get user record by email address

Returns the user record from access permissions by email address

Parameters

email `string` (required) Email address of the user you wish to get the record for.

Endpoint

GET /internal/users/by-email

Example Request

curl -X GET https://portal.hub.gymsystems.co/internal/users/by-email \
  -H "x-api-key: YOUR_API_KEY"

Response

{}

Add or update login provider user ID for a user

Associates a login provider's user ID with an existing user account

Request Body

Endpoint

POST /internal/users/update-login-provider

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/users/update-login-provider \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Check if a user requires 2FA

Returns whether 2FA is required for a given user email (either enabled by user or forced by role)

Request Body

Endpoint

POST /internal/sso-service/check-2fa-status

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/check-2fa-status \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Request password reset

Generates a password reset token and sends an email with reset link to the user

Request Body

Endpoint

POST /internal/sso-service/forgot-password

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/forgot-password \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Reset user password using reset token

Validates a password reset token and updates the user's password. The token must be valid, not expired, and not previously used.

Request Body

Endpoint

POST /internal/sso-service/reset-password

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/reset-password \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Send OTP to user via SMS or email

Sends an OTP code to the user. Attempts SMS first using the user's phone number, then falls back to email if SMS fails or no phone number is available.

Request Body

Endpoint

POST /internal/sso-service/send-otp

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/send-otp \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Validate a user's password

Validates a password against the stored hash for a given user email

Request Body

Endpoint

POST /internal/sso-service/validate-password

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/validate-password \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}

Verify OTP for SSO password validation

Verifies the OTP code sent after successful password validation when 2FA is required

Request Body

Endpoint

POST /internal/sso-service/verify-otp

Example Request

curl -X POST https://portal.hub.gymsystems.co/internal/sso-service/verify-otp \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{}