Esta guía te explica cómo configurar un sitio demo de BioStar Air, conectar y registrar lectores compatibles con BioStar Air en ese sitio, y comenzar a probar tu integración usando nuestras APIs en la nube.
Si ya has trabajado con BioStar 2, muchos conceptos te resultarán familiares; sin embargo, BioStar Air es totalmente nativo en la nube.
Primeros pasos
Requisitos previos
Asegúrate de lo siguiente:
- Contar con un dispositivo compatible con BioStar Aircon firmware cargado de fábrica:
- XP2-AIR, XS2-AIR, BEW3-AIR, BS3-AIR, BLN2-AIR
- Los dispositivos pueden adquirirse a través de distribuidores autorizados de Suprema
- El dispositivo está conectado a internet por Ethernet.
- Tu red permite salida (outbound) por:
- Puerto 443 (HTTPS)
- Puerto 5671 (MQTT sobre TLS)
Paso 1: Configurar el entorno demo y la API Key
1. Registrarse e iniciar sesión
- Ir a: https://developers.biostarair.com/login
- Haz clic en Sign Up, completa el formulario y espera la aprobación.
- Una vez aprobado, inicia sesión con tus credenciales.
2. Crear una aplicación demo
- Ve a API → Management
- Haz clic en + Register
- Elige Demo como tipo de aplicación
- Ingresa un nombre para tu aplicación y haz clic en Register
- Haz clic en Download para descargar un archivo Excel con las credenciales de inicio de sesión del sitio demo (correo y contraseña)
3. Emitir una API Key
- En Application Management, entra a tu aplicación registrada
- Desplázate hasta API Management
- Haz clic en Add
- Ingresa un nombre y confirma. Guarda la clave generada.
4. Iniciar sesión en el portal demo
- Ve al Demo Portal
- Inicia sesión con el correo y la contraseña del archivo Excel
- Ingresa la API Key que acabas de crear
Paso 2: Registrar el lector
Usa la app Airfob Pro Demo (solo Android):
- Descarga la app: https://moca-public-file-share.s3.ap-northeast-2.amazonaws.com/DeviceRegistration.zip
- Inicia sesión con las credenciales del archivo Excel
- Acerca tu teléfono Android al lector (rango BLE) y luego:
- Toca All Menu → Devices → + (esquina superior derecha)
- Ubica tu dispositivo y toca Register
- El lector emitirá un sonido, se reiniciará y aparecerá en Registered Devices
Nota: Los lectores solo pueden registrarse usando la app móvil. El registro por web no está soportado. El registro vía API requiere un certificado criptográfico que no se entrega a los partners.
Paso 3: Administrar el lector
Puedes administrar el dispositivo usando:
- La Airfob Pro Demo App
- El Demo Web Portal: https://demo.airfobspace.com/login
URLs base de la API
| Entorno | URL base |
|---|---|
| Demo | https://demo-afs-api.airfob.com/v1/ |
| Producción - Europa | https://e-afs-api.airfob.com/v1/ |
| Producción - Corea | https://a-afs-api.airfob.com/v1/ (para clientes no-EU) |
Alcance recomendado para la integración
Cuando sea posible, limita tu integración a:
- Gestión del ciclo de vida de usuarios (crear/actualizar/eliminar)
- Gestión de credenciales (móvil, tarjeta RF, biométrico)
Permite que los administradores usen las apps administrativas web y móvil existentes de BioStar Air para:
- Niveles de acceso
- Horarios
- Configuración de puertas y lectores
- Configuración del sitio
Opcional: Flujo de login por API (Postman o programático)
Paso 1 – Login
Endpoint: login
Payload:
{
"username": "tu_correo",
"password": "tu_contraseña"
}
Devuelve un Bearer Token (JWT).
Paso 2 – Obtener cuentas del usuario (Self Accounts)
Endpoint: getSelfAccounts
Autorización: Bearer Token
Devuelve una lista de sitios/cuentas a los que tienes acceso.
Paso 3 – Login a una cuenta
Endpoint: loginAccount
Autorización: Bearer Token
Devuelve un token específico del sitio.
Cómo obtener tu Bearer Token (método con navegador)
Chrome/Edge (Windows o Mac)
- Presiona F12 o Ctrl/Cmd + Shift + I
- Ve a la pestaña Network
- Recarga la página
- Busca llamadas a la API (por ejemplo: groups, login)
- Haz clic en la solicitud
- Ve a la pestaña Headers
- Busca
Authorization: Bearer ...en Request Headers - Clic derecho y copia el token
Safari (Mac)
- Habilita el menú Develop: Safari → Preferences → Advanced → marcar Show Develop menu
- Abre Develop → Show Web Inspector
- Ve a la pestaña Network
- Recarga la página
- Filtra e inspecciona una llamada a la API
- Copia el token
Authorization: Bearerdesde los headers de la solicitud
Llamadas API para gestión de usuarios
Una vez que hayas iniciado sesión, utiliza estos endpoints para gestionar usuarios:
- getUsers
- createUser
- updateUser
- suspendUsers
Incluye siempre el Bearer Token en el header Authorization.
Nota: Para activar un usuario, debes asignar al menos un tipo de credencial (por ejemplo: RF Card, Mobile, Linkpass).
Demo vs Producción
- Sitios demo se crean desde el Developer Portal para pruebas.
- Sitios de producción se crean desde el Partner Portal y requieren site ID, correo del usuario y contraseña. Los sitios de producción solo pueden ser creados por dealers autorizados o por oficinas de Suprema.
Notas importantes
- User ID y Account ID son diferentes: no los confundas.
- Almacena las contraseñas de forma segura si gestionas múltiples sitios.
- Usa siempre el Bearer Token más reciente.
- Los Bearer Tokens copiados desde el navegador pueden reutilizarse en Postman.
¿Necesitas ayuda?
Abre un ticket en el Portal de Soporte Técnico de Suprema: https://support.supremainc.com
Aplicación de ejemplo
¿Necesitas un ejemplo? A continuación se incluye un código de ejemplo para una app en Python que permite suspender usuarios en lote cargando un archivo CSV vía API.
Nota: El siguiente bloque es código y se deja sin traducir para evitar errores de sintaxis.
import requests
import csv
import getpass
from pathlib import Path
def select_server():
servers = {
"1": ("Demo", "https://demo-afs-api.airfob.com/v1"),
"2": ("Global", "https://a-afs-api.airfob.com/v1"),
"3": ("EU", "https://e-afs-api.airfob.com/v1")
}
print("Please select a server:")
for key, (name, _) in servers.items():
print(f"{key}: {name}")
choice = input("Enter server number: ").strip()
return servers.get(choice, (None, None))[1]
def login(base_url, username, password):
url = f"{base_url}/login"
payload = {"username": username, "password": password}
response = requests.post(url, json=payload)
response.raise_for_status()
data = response.json()
token = data.get("access_token")
if not token:
raise ValueError("Login succeeded but no access_token returned.")
print("✅ Login successful.")
return token
def login_to_account(base_url, token, account_id):
url = f"{base_url}/login/{account_id}"
headers = {"Authorization": f"Bearer {token}"}
response = requests.post(url, headers=headers)
response.raise_for_status()
new_token = response.json().get("access_token")
if new_token:
print(f"✅ Switched to account ID: {account_id}")
return new_token
return token
def get_accounts(base_url, token):
url = f"{base_url}/accounts/self"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
response.raise_for_status()
accounts = response.json().get("accounts", [])
return [{"id": acc["id"], "name": acc["site"]["name"]} for acc in accounts]
def suspend_users_from_csv(base_url, csv_path, token):
if not Path(csv_path).exists():
print(f"❌ File not found: {csv_path}")
return
headers = {"Authorization": f"Bearer {token}"}
with open(csv_path, newline='', encoding='utf-8-sig') as f:
reader = csv.DictReader(f)
# Normalize headers
reader.fieldnames = [field.strip().lower() for field in reader.fieldnames]
if 'email' not in reader.fieldnames:
print("❌ Missing required 'email' column in CSV.")
return
for row in reader:
email = row.get("email")
if not email:
print("⚠️ Skipping row with missing email.")
continue
# Search user
search_url = f"{base_url}/users/search"
payload = {"filters": [{"field": "email", "equals": email}]}
search_resp = requests.post(search_url, headers=headers, json=payload)
if search_resp.status_code != 200:
print(f"❌ Failed to search user {email}: {search_resp.text}")
continue
users = search_resp.json().get("users", [])
if not users:
print(f"❌ No user found with email: {email}")
continue
user_id = users[0]["id"]
# Suspend user
suspend_url = f"{base_url}/users/suspend"
suspend_payload = {
"ids": [user_id],
"certify_by": "none",
"use_site_template": True
}
suspend_resp = requests.post(suspend_url, headers=headers, json=suspend_payload)
if suspend_resp.status_code == 200:
print(f"✅ Suspended user: {email}")
else:
print(f"❌ Failed to suspend user {email}: {suspend_resp.text}")
def main():
base_url = select_server()
if not base_url:
print("❌ Invalid selection. Exiting.")
return
print("\n? BioStar Air Login")
username = input("Email: ")
password = getpass.getpass("Password: ")
token = login(base_url, username, password)
accounts = get_accounts(base_url, token)
print("\n? Available Sites:")
for i, acc in enumerate(accounts):
print(f"{i}: {acc['name']} (ID: {acc['id']})")
selected = int(input("\nSelect site number to log into: "))
account_id = accounts[selected]["id"]
token = login_to_account(base_url, token, account_id)
csv_path = input("Enter path to CSV file with user emails: ").strip()
suspend_users_from_csv(base_url, csv_path, token)
if __name__ == "__main__":
main()