Obter tokens de acesso
Troque a credencial de um usuário de serviço por um token de acesso no endpoint /oauth/token, use-o para chamar a API do BreezeAuth e solicite um novo quando ele expirar.
Um usuário de serviço não envia o seu client secret em cada chamada à API. Em vez disso, ele troca a sua credencial por um token de acesso: uma chave de curta duração que ele envia em cada requisição. Isso segue o fluxo client credentials do OAuth 2.0, a forma padrão de máquinas se autenticarem em APIs.
Esta página é técnica. Se você está configurando um usuário de serviço no console de administração, compartilhe-a com os desenvolvedores que vão construir a integração.
Solicitar um token
Envie uma requisição POST para o endpoint de token com o ID do cliente e o client secret da 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 |
Sempre client_credentials. |
client_id |
O ID do cliente da credencial. |
client_secret |
O Client secret da credencial, exibido quando ela foi criada. |
Uma requisição bem-sucedida retorna 200 OK:
{
"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Ij…",
"token_type": "Bearer",
"expires_in": 900
}
| Campo | Descrição |
|---|---|
access_token |
O token a ser enviado nas requisições à API. Trate-o como confidencial, assim como o secret. |
token_type |
Sempre Bearer. |
expires_in |
Por quantos segundos, a partir de agora, o token é válido. Sempre leia esse valor da resposta; não o fixe no código. |
Chamar a API
Envie o token no cabeçalho Authorization de cada requisição:
curl https://api.breezeauth.com/organizations/<organizationsUuid>/memberships \
-H 'Authorization: Bearer <token de acesso>'
Substitua <organizationsUuid> pelo ID da sua organização, exibido abaixo do nome da organização na página
Gerenciar Organização.
O que o usuário de serviço pode fazer depende do seu papel administrativo.
Uma requisição fora desse papel é recusada com 401 Unauthorized.
Quando o token expira: sem refresh tokens
Os tokens de acesso têm curta duração de propósito: se um deles vazar, ele só será útil para um atacante por pouco tempo.
Quando um token expira, a integração simplesmente solicita um novo em /oauth/token com a mesma credencial. Por
isso o BreezeAuth não emite refresh tokens para usuários de serviço, e a resposta não tem o campo refresh_token: um
refresh token existe para que as pessoas não precisem entrar de novo, mas um usuário de serviço possui a sua credencial e
sempre consegue obter um novo token sozinho.
Abordagem recomendada:
- Reutilize um token enquanto ele for válido. Não solicite um novo token antes de cada chamada à API.
- Solicite um novo token pouco antes de terminar o prazo de
expires_in, ou quando uma chamada à API retornar401 Unauthorized. - Se uma requisição continuar retornando
401mesmo com um token novo, pare e avise alguém: provavelmente a credencial ou o usuário de serviço foi desativado.
O que o BreezeAuth verifica
Ao emitir um token, o BreezeAuth verifica se:
- o client ID existe e o client secret confere;
- a credencial está ativa e não passou da data em Expira em;
- o usuário de serviço está Ativo;
- a requisição vem de uma rede permitida, caso a organização tenha uma restrição de acesso por rede.
Em cada requisição à API, o BreezeAuth verifica novamente se:
- o token é válido e não expirou;
- a credencial que o emitiu continua ativa e não expirou, então desativar uma credencial corta os tokens dela imediatamente;
- o usuário de serviço continua Ativo e o seu papel permite a operação;
- a requisição vem de uma rede e de um país permitidos, caso a organização os restrinja.
Erros
| Resposta | Significado | O que fazer |
|---|---|---|
400 Bad Request em /oauth/token |
A requisição está malformada: falta um campo, o grant_type não é client_credentials ou o client_id não é um identificador válido. |
Corrija a requisição. |
401 Unauthorized em /oauth/token |
A credencial não pode ser usada: client ID ou secret incorreto, credencial inativa ou expirada, ou usuário de serviço inativo. Por segurança, a resposta não diz qual é o motivo. | Confira a credencial e o usuário de serviço no console de administração. |
401 Unauthorized com network_not_authorized |
A requisição vem de uma rede fora das zonas de rede permitidas pela organização. | Execute a integração a partir de uma rede permitida ou peça a um administrador para atualizar as zonas. |
401 Unauthorized em uma chamada à API |
O token expirou, a credencial ou o usuário de serviço foi desativado, ou o papel do usuário de serviço não permite a operação. | Solicite um novo token e tente uma vez mais. Se falhar de novo, confira a credencial, o usuário de serviço e o papel. |
403 Forbidden com access_not_allowed_from_country |
A organização restringe o acesso por país, e a requisição vem de um país não permitido. | Execute a integração a partir de um país permitido ou peça a um administrador para revisar a restrição. |
429 Too Many Requests |
Requisições demais em pouco tempo. | Reutilize os tokens em vez de solicitar um por chamada e diminua o ritmo. |
Exemplos de código
Os exemplos abaixo solicitam um token, mantêm-no em memória, renovam-no antes de expirar e tentam uma vez mais quando a
API retorna 401. Eles leem a credencial de variáveis de ambiente.
Node.js
Usa o fetch nativo (Node.js 18 ou superior).
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()
// Renova quando 90% da validade tiver passado, para que o token nunca expire no meio de uma requisição.
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) {
// O token pode ter expirado ou sido invalidado: obtém um novo e tenta uma vez mais.
cachedToken = null
response = await send()
}
return response
}
// Exemplo: listar os usuários da organização.
// 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()
# Renova quando 90% da validade tiver passado, para que o token nunca expire no meio de uma requisição.
_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:
# O token pode ter expirado ou sido invalidado: obtém um novo e tenta uma vez mais.
_cached_token = None
response = send()
return response
# Exemplo: listar os usuários da organização.
# response = breezeauth_request("GET", f"/organizations/{organization_id}/memberships")
Última atualização: 13 de outubro de 2026