REST API Reference
The HospitalityNet API provides programmatic access to all platform data. Manage properties, access points, guest sessions, support tickets, and more — all through a simple, consistent RESTful interface.
API Base URL
All API requests are relative to the base URL. The platform uses relative URLs so it works in any deployment environment without configuration changes.
Authentication
The platform API is currently session-scoped and authorization-free for same-project requests. All requests from within the platform web app are automatically authenticated via the project session context.
Project-scoped access: The RESTful Table API automatically scopes all reads and writes to your specific project (gs_project_id). You cannot access data from other projects. No API key is required for intra-project requests.
External API access: For server-to-server or third-party integration scenarios, contact the platform team to obtain an API token. Include it as: Authorization: Bearer {your_token}
System Fields
Every record automatically receives these system-managed fields:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique record identifier, auto-generated |
gs_project_id | string | Your project identifier (auto-set) |
gs_table_name | string | Table name (auto-set) |
created_at | number (ms) | Unix timestamp in milliseconds of creation |
updated_at | number (ms) | Unix timestamp in milliseconds of last update |
Pagination & Filtering
All list endpoints support pagination, search, and sorting via query parameters.
| Parameter | Default | Description |
|---|---|---|
page optional | 1 | Page number (1-based) |
limit optional | 100 | Records per page (max 500) |
search optional | — | Full-text search across all text fields |
sort optional | created_at | Field to sort by (prefix with - for descending) |
List Response Format
{
"data": [ /* array of record objects */ ],
"total": 42, // total matching records
"page": 1, // current page
"limit": 10, // records per page
"table": "properties", // table name
"schema": { /* field definitions */ }
}
Example Requests
# First 10 properties GET tables/properties?page=1&limit=10 # Search for Mumbai properties GET tables/properties?search=Mumbai # Sort by health score descending GET tables/properties?sort=-health_pct # Combine: search + paginate GET tables/properties?search=online&page=2&limit=20
HTTP Status Codes & Errors
The API uses standard HTTP status codes. Errors return a JSON body with a descriptive message.
Error Response Format
{
"error": "CONFLICT",
"message": "Entity with the specified id already exists in the system.",
"status": 409,
"request_id": "req_a8f2c1d9e3b7"
}
Rate Limiting
Rate limits are applied per project to ensure fair usage and platform stability.
| Operation | Limit | Window | Notes |
|---|---|---|---|
| GET (read) | 1000 req | per minute | Per project |
| POST (create) | 100 req | per minute | Per project |
| PUT / PATCH (update) | 200 req | per minute | Per project |
| DELETE | 50 req | per minute | Per project |
| Bulk operations | 10 req | per minute | Batch inserts / updates |
When rate limit is exceeded, the API returns HTTP 429. Implement exponential backoff: wait 2^attempt × 100ms before retrying. The Retry-After header indicates when you may retry.
Database Tables
The platform organises all data into 15 structured tables. Each table has a dedicated REST endpoint and full CRUD support.
Properties
Hotels, resorts, clubs, and venues managed by the MSP. The central entity to which all devices, users, sessions, and events are linked.
Query Parameters
| Param | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Per-page results (default: 100) |
search | string | Search by name, city, state, ISP |
sort | string | name, -health_pct, city, created_at |
JavaScript Example
const getProperties = async (page = 1, search = '') => { const params = new URLSearchParams({ page, limit: 20, search }); const res = await fetch(`tables/properties?${params}`); if (!res.ok) throw new Error(`API ${res.status}`); return res.json(); // { data, total, page, limit } };
const res = await fetch('tables/properties/prop-001'); const property = await res.json(); // Returns: { id, name, city, health_pct, ap_count, ... }
Required Fields
| Field | Type | Description |
|---|---|---|
id required | string | Unique ID e.g. prop-007 |
name required | string | Property display name |
group_id | string | FK → hotel_groups.id |
city | string | City |
state | string | State |
type | string | e.g. 5-Star Hotel, Resort & Spa |
status | string | online | warning | offline |
Request Body Example
const res = await fetch('tables/properties', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: 'prop-007', name: 'The Leela Palace Delhi', group_id: 'grp-006', type: '5-Star Hotel', status: 'online', city: 'New Delhi', state: 'Delhi', ap_count: 64, health_pct: 98, isp_name: 'Airtel Leased Line', sla_uptime_pct: 99.9 }) }); // HTTP 201 Created const created = await res.json();
// Update only health score and active guests await fetch('tables/properties/prop-001', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ health_pct: 96, active_guests: 438, bandwidth_mbps: 672 }) });
Deletion is a soft delete. The record is flagged deleted=true and excluded from all future queries. It cannot be undone via the API. Returns HTTP 204 No Content on success.
await fetch('tables/properties/prop-007', { method: 'DELETE' }); // HTTP 204 — no response body
Hotel Groups
Hotel chains and groups that own one or more properties. Groups aggregate metrics across all their properties.
Key Fields
| Field | Type | Description |
|---|---|---|
id | string | Group ID e.g. grp-001 |
name | string | Group name |
property_count | number | Total properties in group |
total_aps | number | Total APs across all properties |
group_health_score | number | Aggregate health score 0–100 |
contract_tier | string | enterprise | professional | standard |
Access Points
WiFi access points installed across properties. Track status, clients, signal quality, POE draw, firmware, and more.
Key Fields
| Field | Type | Description |
|---|---|---|
property_id | string | FK → properties.id |
name | string | AP label e.g. AP-GH-F01-Lobby |
status | string | online | warning | offline |
clients | number | Currently connected client count |
rssi | number | Average signal strength in dBm |
poe_switch | string | Connected POE switch name |
poe_port | number | POE switch port number |
firmware | string | Current firmware version |
last_seen | datetime | Last heartbeat timestamp |
Filter APs by Property
// Get all APs for a property (client-side filter) const { data } = await (await fetch('tables/access_points?limit=500')).json(); const propertyAPs = data.filter(ap => ap.property_id === 'prop-001'); const offlineAPs = propertyAPs.filter(ap => ap.status === 'offline');
// Mark AP offline after failed ping await fetch(`tables/access_points/ap-005`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'offline', clients: 0, last_seen: new Date().toISOString() }) });
Guest Sessions
Track individual WiFi sessions per guest device. Includes device info, signal quality, data usage, authentication method, and session timing.
Key Fields
| Field | Type | Description |
|---|---|---|
property_id | string | FK → properties.id |
ap_id | string | FK → access_points.id |
guest_name | string | Guest display name |
mac | string | Client MAC address |
device_type | string | iPhone, MacBook, Android, Laptop, etc. |
status | string | active | disconnected | expired |
auth_method | string | pms | voucher | social | bypass |
download_mb | number | Total downloaded data in MB |
login_time | datetime | Session start |
logout_time | datetime | Session end (null if active) |
Support Tickets
Help desk tickets raised by property staff or auto-generated by the NOC. Track priority, assignment, SLA, and resolution.
Key Fields
| Field | Type | Description |
|---|---|---|
property_id | string | FK → properties.id |
subject | string | Short issue summary |
status | string | open | in-progress | resolved | closed |
priority | string | critical | high | medium | low |
category | string | AP-Offline, Slow-WiFi, Coverage, etc. |
assigned_to | string | MSP staff ID FK → msp_staff.id |
sla_breach | bool | True if SLA deadline missed |
opened_at | datetime | Ticket creation time |
resolved_at | datetime | Resolution timestamp |
Get Open Tickets Example
const { data } = await (await fetch( 'tables/support_tickets?sort=-opened_at&limit=50' )).json(); const openCritical = data.filter(t => t.status === 'open' && t.priority === 'critical' );
// Resolve a ticket await fetch('tables/support_tickets/tkt-001', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'resolved', resolved_at: new Date().toISOString(), resolution_note: 'Replaced faulty POE switch port. AP back online.' }) });
Vouchers
WiFi access vouchers for guest authentication. Supports single-use, multi-use, and unlimited types with time and bandwidth controls.
Key Fields
| Field | Type | Description |
|---|---|---|
code | string | Voucher code guests enter |
type | string | single-use | multi-use | unlimited | time-based |
status | string | active | used | expired | revoked |
duration_min | number | Session duration in minutes |
bandwidth_down_mbps | number | Per-session download cap |
valid_until | datetime | Voucher expiry |
// Generate a 24-hour guest voucher const code = Math.random().toString(36).substring(2, 8).toUpperCase(); await fetch('tables/vouchers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: `vch-${Date.now()}`, property_id: 'prop-001', code, type: 'single-use', status: 'active', max_uses: 1, current_uses: 0, duration_min: 1440, bandwidth_down_mbps: 25, bandwidth_up_mbps: 10, valid_from: new Date().toISOString(), valid_until: new Date(Date.now() + 86400000).toISOString() }) });
Switches
Network switches providing POE power and uplink connectivity to access points. Monitor port usage, temperature, CPU, and POE budget.
MSP Staff
Internal MSP team members including NOC engineers, field engineers, account managers, and administrators.
Property Users
Property-side staff accounts with role-based permissions to access the property portal, raise tickets, and view guests.
SSID Profiles
WiFi network configurations per property. Controls security, captive portal, bandwidth limits, VLAN, and scheduling.
ISP Contracts
ISP service agreements including account details, speed, SLA terms, support contacts, and billing information per property.
Bandwidth Snapshots
Time-series bandwidth telemetry per property. Snapshots record total download/upload, per-VLAN breakdown, and active client counts.
Tip: Post a new snapshot every 5 minutes from your monitoring agent to build historical bandwidth trends. Use the sort=-timestamp query param to always get the latest reading first.
Network Events
Auto-generated alerts and events: AP offline, high interference, ISP failover, link down, config changes, and more.
Network Topology
Saved topology diagram snapshots per property. Stores serialised node/link arrays for rendering the interactive topology canvas.
Audit Logs
Immutable audit trail of all user actions: config changes, logins, ticket updates, AP reboots, voucher creation, and deletions.
Read-only: Audit log records should never be updated or deleted. Only POST (create) is permitted. Enforce this at the application layer.
// Log a config change action async function auditLog(action, resource, changes) { await fetch('tables/audit_logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: `alog-${Date.now()}`, actor_id: 'msp-001', actor_name: 'Vikram Patel', actor_role: 'super-admin', action, resource_type: resource.type, resource_id: resource.id, resource_name: resource.name, changes: JSON.stringify(changes), ip_address: '103.21.58.10', occurred_at: new Date().toISOString() }) }); }
JavaScript SDK Pattern
A reusable API client class for the HospitalityNet platform. Copy this into your project to get a consistent, error-handled API layer.
/** * HospitalityNet API Client * Provides typed CRUD access to all 15 platform tables. */ class HNetAPI { constructor(baseUrl = '') { this.base = baseUrl; } async #req(method, path, body) { const opts = { method, headers: { 'Content-Type': 'application/json' } }; if (body) opts.body = JSON.stringify(body); const res = await fetch(`${this.base}${path}`, opts); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.message || `HTTP ${res.status}`); } return res.status === 204 ? null : res.json(); } // List records with optional search/sort/page list(table, params = {}) { const q = new URLSearchParams(params).toString(); return this.#req('GET', `tables/${table}${q ? '?' + q : ''}`); } // Get single record by ID get(table, id) { return this.#req('GET', `tables/${table}/${id}`); } create(table, data) { return this.#req('POST', `tables/${table}`, data); } update(table, id, data) { return this.#req('PUT', `tables/${table}/${id}`, data); } patch(table, id, data) { return this.#req('PATCH', `tables/${table}/${id}`, data); } delete(table, id) { return this.#req('DELETE', `tables/${table}/${id}`); } } // Usage const api = new HNetAPI(); // Get all online properties const { data: props } = await api.list('properties', { search: 'online', sort: '-health_pct' }); // Create a support ticket const ticket = await api.create('support_tickets', { id: `tkt-${Date.now()}`, property_id: 'prop-001', subject: 'AP offline in Room 704 corridor', priority: 'high', status: 'open', category: 'AP-Offline' }); // Resolve it later await api.patch('support_tickets', ticket.id, { status: 'resolved', resolved_at: new Date().toISOString() });
Python SDK Pattern
A Python requests-based client for server-to-server or monitoring agent use cases.
import requests from datetime import datetime, timezone import time class HNetAPIClient: def __init__(self, base_url: str, max_retries: int = 3): self.base = base_url.rstrip('/') self.session = requests.Session() self.session.headers.update({'Content-Type': 'application/json'}) self.max_retries = max_retries def _request(self, method, path, **kwargs): url = f"{self.base}/{path}" for attempt in range(self.max_retries): r = self.session.request(method, url, **kwargs) if r.status_code == 429: time.sleep(2 ** attempt * 0.1) continue r.raise_for_status() return r.json() if r.content else None def list(self, table, **params): return self._request('GET', f'tables/{table}', params=params) def get(self, table, record_id): return self._request('GET', f'tables/{table}/{record_id}') def create(self, table, data: dict): return self._request('POST', f'tables/{table}', json=data) def patch(self, table, record_id, data: dict): return self._request('PATCH', f'tables/{table}/{record_id}', json=data) def delete(self, table, record_id): return self._request('DELETE', f'tables/{table}/{record_id}') # Usage api = HNetAPIClient('https://your-platform-url') # Post bandwidth snapshot api.create('bandwidth_snapshots', { 'id': f"bw-{int(time.time())}", 'property_id': 'prop-001', 'timestamp': datetime.now(timezone.utc).isoformat(), 'total_download_mbps': 648, 'total_upload_mbps': 142, 'active_clients': 412, 'interval_min': 5 })
cURL Examples
Quick reference for testing API endpoints from the command line.
# List all properties curl -s "tables/properties?limit=10&sort=-health_pct" | python3 -m json.tool # Get single property curl -s "tables/properties/prop-001" # Create a new property curl -X POST "tables/properties" \ -H "Content-Type: application/json" \ -d '{ "id": "prop-007", "name": "The Leela Palace Delhi", "type": "5-Star Hotel", "status": "online", "city": "New Delhi", "state": "Delhi", "health_pct": 98 }' # Update AP status to offline curl -X PATCH "tables/access_points/ap-005" \ -H "Content-Type: application/json" \ -d '{"status": "offline", "clients": 0}' # Resolve a support ticket curl -X PATCH "tables/support_tickets/tkt-001" \ -H "Content-Type: application/json" \ -d '{"status": "resolved", "resolved_at": "2025-05-19T12:00:00Z"}' # Delete a record curl -X DELETE "tables/vouchers/vch-006" -i # Expect: HTTP/1.1 204 No Content
Testing locally: Use jq to pretty-print responses: curl -s "tables/properties" | jq '.data[].name'. Install with brew install jq (macOS) or apt install jq (Linux).