Lango

API reference

Base URL: https://lango.localtel.tech/api/v1. The machine-readable OpenAPI spec is at /api/v1/openapi.json.

Authentication

Create keys in your portal under PMS & API → API keys. Send the key as a bearer token:

Authorization: Bearer cpk_live_xxxxxxxxxxxxxxxx
ScopeAllowsPackage
guests:writecheck-in, update, move, check-out, full resyncall
guests:readlist in-house guests / directoryall
portal:readlist sites and plansall
sessions:readlist Wi-Fi sessionsProfessional+
sessions:writedisconnect sessionsProfessional+
vouchers:writecreate access codesProfessional+

{site} in paths accepts either the site ID (sit_…) or the site key shown in your portal.

Guests / directory

The guest model is generic across sectors. room is whatever people type as their identifier: a room, bed, unit, student ID or ticket number. last_name is the second factor: a surname, PIN or date of birth.

FieldTypeNotes
reservation_idstring, requiredStable key from your system (reservation, admission, enrolment, ticket ID)
roomstring, requiredIdentifier typed at login
last_namestring, requiredSecond factor typed at login (accent- and case-insensitive)
first_name, email, language, vipstringOptional
arrival, departuredate (YYYY-MM-DD)departure caps Wi-Fi access at checkout time + grace
no_postbooleanBlocks charge-to-room upgrades

Check in

POST /sites/{site}/guests/checkin
{"reservation_id":"884213","room":"1204","last_name":"Otieno","first_name":"Amani","arrival":"2026-11-13","departure":"2026-11-16"}
→ 201 {"data":{"id":"gst_…","room":"1204","status":"in_house",…}}

Update, move, check out

POST /sites/{site}/guests/update    {"reservation_id":"884213","departure":"2026-11-18"}
POST /sites/{site}/guests/move      {"reservation_id":"884213","new_room":"1402"}
POST /sites/{site}/guests/checkout  {"reservation_id":"884213"}         → disconnects the guest's devices

Full resync (nightly)

PUT /sites/{site}/guests
{"guests":[{"reservation_id":"884213","room":"1204","last_name":"Otieno"}, …]}
→ {"data":{"upserted":212,"checked_out":7}}

Anyone not in the list is checked out. Each call accepts up to 5,000 guests.

List

GET /sites/{site}/guests?status=in_house|checked_out

Sessions

GET    /sites/{site}/sessions?status=live|all
DELETE /sites/{site}/sessions/{id}          → disconnect now (RADIUS Disconnect / controller API)

Access codes

POST /sites/{site}/vouchers
{"plan_id":"pln_…","count":50,"max_uses":1,"valid_hours":72,"note":"Conference hall B"}

Send "code":"SUMMIT2026" to create one shared code.

Plans & sites

GET /sites                       → sites this key can access, with splash URLs
GET /sites/{site}/plans          → active plans (free tiers and paid upgrades)

Errors

Errors come back as JSON: {"error":"message","details":{…}}.

StatusMeaning
401Missing or invalid key
403Missing scope, wrong site, tenant suspended, or feature not in package
404Not found
422Validation failed (details lists the fields)
429Rate limited

Webhooks

Configure them under PMS & API → Outbound webhook (Professional and above). Each delivery is a POST with:

X-Portal-Event: session.created
X-Portal-Timestamp: 1763030400
X-Portal-Signature: sha256=<hex HMAC_SHA256(secret, timestamp + "." + body)>

{"id":"evt_…","event":"session.created","created_at":"…","tenant_id":"…","site_id":"…","data":{…}}

Events:

Device integration endpoints

These are used by your network equipment, not by your code:

PurposeEndpoint
Splash pageGET /p/{site-key} (+ vendor parameters)
UniFi external portalGET /guest/s/{unifi-site}/
Welcome pageGET /p/{site-key}/welcome
RADIUSUDP 1812 (auth), 1813 (accounting); the platform sends CoA/Disconnect to UDP 3799