Obtener tokens de acceso
Intercambia la credencial de un usuario de servicio por un token de acceso en el endpoint /oauth/token, úsalo para llamar a la API de BreezeAuth y solicita uno nuevo cuando caduque.
Un usuario de servicio no envía su client secret en cada llamada a la API. En su lugar, intercambia su credencial por un token de acceso: una clave de corta duración que después envía en cada petición. Esto sigue el flujo client credentials de OAuth 2.0, la forma estándar en que las máquinas se autentican ante las API.
Esta página es técnica. Si estás configurando un usuario de servicio en la consola de administración, compártela con los desarrolladores que vayan a construir la integración.
Solicitar un token
Envía una petición POST al endpoint de tokens con el ID de cliente y el client secret de la credencial:
curl -X POST https://api.breezeauth.com/oauth/token \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "5f0c3a8e-2b7d-4e91-9a6c-1d2e3f4a5b6c",
"client_secret": "<client secret>"
}'
| Campo | Valor |
|---|---|
grant_type |
Siempre client_credentials. |
client_id |
El ID de cliente de la credencial. |
client_secret |
El Client secret de la credencial, mostrado cuando se creó. |
Una petición correcta devuelve 200 OK:
{
"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Ij…",
"token_type": "Bearer",
"expires_in": 900
}
| Campo | Descripción |
|---|---|
access_token |
El token que debes enviar en las peticiones a la API. Trátalo como confidencial, igual que el secret. |
token_type |
Siempre Bearer. |
expires_in |
Durante cuántos segundos, desde ahora, es válido el token. Léelo siempre de la respuesta; no lo fijes en el código. |
Llamar a la API
Envía el token en la cabecera Authorization de cada petición:
curl https://api.breezeauth.com/organizations/<organizationsUuid>/memberships \
-H 'Authorization: Bearer <token de acceso>'
Sustituye <organizationsUuid> por el ID de tu organización, que aparece debajo del nombre de la organización en la
página Gestionar organización.
Lo que puede hacer el usuario de servicio depende de su rol administrativo. Una
petición fuera de ese rol se rechaza con 401 Unauthorized.
Cuando el token caduca: sin refresh tokens
Los tokens de acceso son de corta duración a propósito: si uno se filtra, solo le sirve a un atacante durante poco tiempo.
Cuando un token caduca, la integración simplemente solicita uno nuevo a /oauth/token con la misma credencial. Por eso
BreezeAuth no emite refresh tokens para los usuarios de servicio, y la respuesta no tiene ningún campo
refresh_token: un refresh token existe para que las personas no tengan que volver a iniciar sesión, pero un usuario de
servicio tiene su credencial y siempre puede obtener un token nuevo por sí mismo.
Enfoque recomendado:
- Reutiliza un token mientras sea válido. No solicites un token nuevo antes de cada llamada a la API.
- Solicita un token nuevo poco antes de que se agote
expires_in, o cuando una llamada a la API devuelva401 Unauthorized. - Si una petición sigue devolviendo
401con un token recién obtenido, detente y avisa a alguien: probablemente se ha desactivado la credencial o el usuario de servicio.
Qué comprueba BreezeAuth
Al emitir un token, BreezeAuth comprueba que:
- el client ID existe y el client secret coincide;
- la credencial está activa y no ha superado su fecha de Caduca el;
- el usuario de servicio está Activo;
- la petición procede de una red permitida, si la organización tiene una restricción de acceso por red.
En cada petición a la API, BreezeAuth comprueba de nuevo que:
- el token es válido y no ha caducado;
- la credencial que lo emitió sigue activa y no ha caducado, por lo que desactivar una credencial corta sus tokens de inmediato;
- el usuario de servicio sigue Activo y su rol permite la operación;
- la petición procede de una red y de un país permitidos, si la organización los restringe.
Errores
| Respuesta | Significado | Qué hacer |
|---|---|---|
400 Bad Request en /oauth/token |
La petición está mal formada: falta un campo, grant_type no es client_credentials o client_id no es un identificador válido. |
Corrige la petición. |
401 Unauthorized en /oauth/token |
La credencial no se puede usar: client ID o secret incorrectos, credencial inactiva o caducada, o usuario de servicio inactivo. Por seguridad, la respuesta no indica el motivo. | Revisa la credencial y el usuario de servicio en la consola de administración. |
401 Unauthorized con network_not_authorized |
La petición procede de una red que no está entre las zonas de red permitidas por la organización. | Ejecuta la integración desde una red permitida o pide a un administrador que actualice las zonas. |
401 Unauthorized en una llamada a la API |
El token ha caducado, se ha desactivado su credencial o el usuario de servicio, o el rol del usuario de servicio no permite la operación. | Solicita un token nuevo y reintenta una vez. Si vuelve a fallar, revisa la credencial, el usuario de servicio y su rol. |
403 Forbidden con access_not_allowed_from_country |
La organización restringe el acceso por país y la petición procede de un país no permitido. | Ejecuta la integración desde un país permitido o pide a un administrador que revise la restricción. |
429 Too Many Requests |
Demasiadas peticiones en poco tiempo. | Reutiliza los tokens en lugar de solicitar uno por llamada y reduce el ritmo. |
Ejemplos de código
Los ejemplos siguientes solicitan un token, lo guardan en memoria, lo renuevan antes de que caduque y reintentan una vez
cuando la API devuelve 401. Leen la credencial de variables de entorno.
Node.js
Usa el fetch integrado (Node.js 18 o posterior).
const API_URL = 'https://api.breezeauth.com'
let cachedToken = null // { value, renewAt }
async function getAccessToken() {
if (cachedToken && Date.now() < cachedToken.renewAt) {
return cachedToken.value
}
const response = await fetch(`${API_URL}/oauth/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: process.env.BREEZEAUTH_CLIENT_ID,
client_secret: process.env.BREEZEAUTH_CLIENT_SECRET,
}),
})
if (!response.ok) {
throw new Error(`BreezeAuth token request failed with status ${response.status}`)
}
const { access_token, expires_in } = await response.json()
// Renueva cuando haya pasado el 90 % de la validez, para que el token nunca caduque en mitad de una petición.
cachedToken = { value: access_token, renewAt: Date.now() + expires_in * 1000 * 0.9 }
return cachedToken.value
}
export async function breezeAuthRequest(path, options = {}) {
const send = async () =>
fetch(`${API_URL}${path}`, {
...options,
headers: { ...options.headers, Authorization: `Bearer ${await getAccessToken()}` },
})
let response = await send()
if (response.status === 401) {
// Puede que el token haya caducado o se haya invalidado: obtiene uno nuevo y reintenta una vez.
cachedToken = null
response = await send()
}
return response
}
// Ejemplo: listar los usuarios de la organización.
// const response = await breezeAuthRequest(`/organizations/${organizationId}/memberships`)
Python
Usa requests.
import os
import time
import requests
API_URL = "https://api.breezeauth.com"
_cached_token = None # (value, renew_at)
def get_access_token():
global _cached_token
if _cached_token and time.time() < _cached_token[1]:
return _cached_token[0]
response = requests.post(
f"{API_URL}/oauth/token",
json={
"grant_type": "client_credentials",
"client_id": os.environ["BREEZEAUTH_CLIENT_ID"],
"client_secret": os.environ["BREEZEAUTH_CLIENT_SECRET"],
},
timeout=10,
)
response.raise_for_status()
body = response.json()
# Renueva cuando haya pasado el 90 % de la validez, para que el token nunca caduque en mitad de una petición.
_cached_token = (body["access_token"], time.time() + body["expires_in"] * 0.9)
return _cached_token[0]
def breezeauth_request(method, path, headers=None, **kwargs):
global _cached_token
def send():
all_headers = {**(headers or {}), "Authorization": f"Bearer {get_access_token()}"}
return requests.request(method, f"{API_URL}{path}", headers=all_headers, timeout=30, **kwargs)
response = send()
if response.status_code == 401:
# Puede que el token haya caducado o se haya invalidado: obtiene uno nuevo y reintenta una vez.
_cached_token = None
response = send()
return response
# Ejemplo: listar los usuarios de la organización.
# response = breezeauth_request("GET", f"/organizations/{organization_id}/memberships")
Última actualización: 13 de octubre de 2026