Authentication
The SalonBookIt API uses two authentication methods: API Keys to identify your business and JWT to authenticate customers.
Overview
API Key
Identifies your business in each request. Required for all endpoints.
- Obtained from the Dashboard
- Sent in the header
X-API-Key - Prefix
hh_pub_(pública) ohh_sec_(privada)
JWT Token
Authenticates a specific customer. Required for private endpoints.
- Obtained via
/api/v1/auth/login/ - Sent in the header
Authorization - Expires in 24 hours
API Keys
Your API Key identifies your business and must be included in all API requests.
Get your API Key
- Log in to your Dashboard
- Go to Configuration → Integrations
- Click on Generate New API Key
- Asigna un nombre descriptivo (ej: "Widget Web", "App Móvil")
- Copy and save the API Key securely
Use the API Key
Include your API Key in the header X-API-Key of each request:
curl -X GET "https://app.salonbookit.com/api/v1/negocio/" \
-H "X-API-Key: hh_pub_live_abc123def456..."
const response = await fetch('https://app.salonbookit.com/api/v1/servicios/', {
headers: {
'X-API-Key': 'hh_pub_live_abc123def456...'
}
});
const data = await response.json();
import requests
response = requests.get(
'https://app.salonbookit.com/api/v1/servicios/',
headers={'X-API-Key': 'hh_pub_live_abc123def456...'}
)
data = response.json()
$ch = curl_init('https://app.salonbookit.com/api/v1/servicios/');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: hh_pub_live_abc123def456...'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
API Key types
Las API Keys tienen dos dimensiones: tipo (pública/privada) y entorno (producción/pruebas).
Por tipo
| Prefix | Type | Usage |
|---|---|---|
hh_pub_ |
Pública | Para widgets y frontend. Permisos limitados a lectura y crear reservas. |
hh_sec_ |
Privada | Para backend. No exponer en código cliente. |
Por entorno
| Sufijo | Environment | Usage |
|---|---|---|
_live_ |
Production | Real data, real transactions |
_test_ |
Testing | Test data, no real charges |
Ejemplos de formatos completos:
hh_pub_live_...- Pública de producción (para widgets en producción)hh_pub_test_...- Pública de pruebas (para desarrollo de widgets)hh_sec_live_...- Privada de producción (para tu backend)hh_sec_test_...- Privada de pruebas (para desarrollo backend)
Never include your API Key in client-side code that is publicly visible. For the widget, we use an API Key with limited permissions that only allows read operations and booking creation.
JWT Authentication
Endpoints requiring customer authentication use JWT tokens. These endpoints include:
- View customer bookings
- View/modify customer profile
- Check loyalty points
- View order history
Get a JWT token
/api/v1/auth/login/
Request
curl -X POST "https://app.salonbookit.com/api/v1/auth/login/" \
-H "X-API-Key: hh_pub_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"email": "cliente@ejemplo.com",
"password": "contraseña123"
}'
Response (200 OK) - Customer
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tipo": "cliente",
"cliente": {
"id": 123,
"nombre": "Juan",
"apellido": "García",
"email": "cliente@ejemplo.com",
"telefono": "+34612345678",
"puntos": 150,
"nivel": "gold"
}
}
}
Response (200 OK) - Staff
Si las credenciales corresponden a un miembro del staff:
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tipo": "staff",
"staff": {
"id": 1,
"nombre": "María",
"apellido": "López",
"email": "maria@salon.com",
"telefono": "+34612345678",
"rol": "admin",
"permisos": {
"puede_ver_reservas": true,
"puede_crear_reservas": true,
"puede_ver_clientes": true
}
}
}
}
Use the JWT token
Include the token in the header Authorization with the prefix Bearer:
curl -X GET "https://app.salonbookit.com/api/v1/cliente/reservas/" \
-H "X-API-Key: hh_pub_live_abc123..." \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Renew the token
Tokens expire in 24 hours. Use the refresh endpoint to get a new one:
/api/v1/auth/refresh/
curl -X POST "https://app.salonbookit.com/api/v1/auth/refresh/" \
-H "X-API-Key: hh_pub_live_abc123..." \
-H "Authorization: Bearer TOKEN_ACTUAL"
Rate Limiting
The API has request limits to ensure stable service:
| Limit | Window | Description |
|---|---|---|
| 120 requests | 1 minute | General limit per API Key |
| 20 attempts | 15 minutes | Login (by IP) |
| 10 attempts | 1 hour | Registration (by IP) |
Rate Limit Headers
Each response includes informational headers:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 115
X-RateLimit-Reset: 1704067200
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum number of allowed requests |
X-RateLimit-Remaining |
Remaining requests in the current window |
X-RateLimit-Reset |
Unix timestamp when the counter resets |
Error 429: Too Many Requests
If you exceed the limit, you'll receive a 429 error:
{
"success": false,
"error": "You have exceeded the request limit. Try again in 45 seconds.",
"code": "RATE_LIMIT_EXCEEDED"
}
Authentication errors
| Code | HTTP Status | Description |
|---|---|---|
MISSING_API_KEY |
401 | X-API-Key header was not included |
INVALID_API_KEY |
401 | Invalid or not found API Key |
API_KEY_DISABLED |
403 | API Key has been disabled |
API_KEY_EXPIRED |
403 | API Key has expired |
INVALID_TOKEN |
401 | Invalid or malformed JWT Token |
TOKEN_EXPIRED |
401 | Expired JWT Token |
INVALID_CREDENTIALS |
401 | Incorrect email or password |