Autenticação
A API usa JWT Bearer tokens. Toda requisição (exceto GET /health e o endpoint de webhook) deve incluir o header Authorization.
O administrador da plataforma fornece três credenciais necessárias:
| Credencial | Variável | Descrição |
|---|---|---|
| URL de autenticação | AUTH_URL | Endpoint base do serviço de auth |
| Chave pública | AUTH_PUBLIC_KEY | Chave de acesso público (não secreta) |
| Email + senha | — | Credenciais do seu usuário |
Visão geral do fluxo
Obtendo o token
Faça um POST ao endpoint de autenticação com email e senha:
POST {AUTH_URL}/auth/v1/token?grant_type=password
- Python
- JavaScript
- Shell
- Ruby
import requests
AUTH_URL = "<AUTH_URL>"
AUTH_PUBLIC_KEY = "<AUTH_PUBLIC_KEY>"
def get_token(email: str, password: str) -> tuple[str, str]:
resp = requests.post(
f"{AUTH_URL}/auth/v1/token?grant_type=password",
headers={
"apikey": AUTH_PUBLIC_KEY,
"Content-Type": "application/json",
},
json={"email": email, "password": password},
)
resp.raise_for_status()
data = resp.json()
return data["access_token"], data["refresh_token"]
access_token, refresh_token = get_token("usuario@empresa.com", "senha123")
const AUTH_URL = "<AUTH_URL>";
const AUTH_PUBLIC_KEY = "<AUTH_PUBLIC_KEY>";
async function getToken(email, password) {
const resp = await fetch(
`${AUTH_URL}/auth/v1/token?grant_type=password`,
{
method: "POST",
headers: {
apikey: AUTH_PUBLIC_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
}
);
if (!resp.ok) throw new Error(`Auth failed: ${resp.status}`);
const { access_token, refresh_token } = await resp.json();
return { access_token, refresh_token };
}
AUTH_URL="<AUTH_URL>"
AUTH_PUBLIC_KEY="<AUTH_PUBLIC_KEY>"
AUTH_RESP=$(curl -s -X POST \
"${AUTH_URL}/auth/v1/token?grant_type=password" \
-H "apikey: ${AUTH_PUBLIC_KEY}" \
-H "Content-Type: application/json" \
-d '{"email":"usuario@empresa.com","password":"senha123"}')
TOKEN=$(echo "$AUTH_RESP" | jq -r '.access_token')
REFRESH_TOKEN=$(echo "$AUTH_RESP" | jq -r '.refresh_token')
require 'net/http'
require 'json'
AUTH_URL = "<AUTH_URL>"
AUTH_PUBLIC_KEY = "<AUTH_PUBLIC_KEY>"
def get_token(email, password)
uri = URI("#{AUTH_URL}/auth/v1/token?grant_type=password")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req['apikey'] = AUTH_PUBLIC_KEY
req['Content-Type'] = 'application/json'
req.body = JSON.dump(email: email, password: password)
resp = http.request(req)
raise "Auth failed: #{resp.code}" unless resp.is_a?(Net::HTTPSuccess)
data = JSON.parse(resp.body)
[data['access_token'], data['refresh_token']]
end
access_token, refresh_token = get_token('usuario@empresa.com', 'senha123')
Usando o token nas requisições
Inclua o token no header Authorization em todas as requisições autenticadas:
Authorization: Bearer <access_token>
- Python
- JavaScript
- Shell
- Ruby
BASE_URL = "https://api-fastdelivery.obotzap.com"
headers = {"Authorization": f"Bearer {access_token}"}
resp = requests.get(f"{BASE_URL}/api/v1/deliveries", headers=headers)
const BASE_URL = "https://api-fastdelivery.obotzap.com";
const headers = { Authorization: `Bearer ${access_token}` };
const resp = await fetch(`${BASE_URL}/api/v1/deliveries`, { headers });
curl -s "${BASE_URL}/api/v1/deliveries" \
-H "Authorization: Bearer ${TOKEN}"
BASE_URL = "https://api-fastdelivery.obotzap.com"
req = Net::HTTP::Get.new(URI("#{BASE_URL}/api/v1/deliveries"))
req['Authorization'] = "Bearer #{access_token}"
Expiração e refresh
O token expira em 1 hora. Use o refresh_token para obter um novo access_token sem reautenticar:
POST {AUTH_URL}/auth/v1/token?grant_type=refresh_token
- Python
- JavaScript
- Shell
- Ruby
def refresh_access_token(refresh_token: str) -> str:
resp = requests.post(
f"{AUTH_URL}/auth/v1/token?grant_type=refresh_token",
headers={
"apikey": AUTH_PUBLIC_KEY,
"Content-Type": "application/json",
},
json={"refresh_token": refresh_token},
)
resp.raise_for_status()
return resp.json()["access_token"]
async function refreshToken(refreshToken) {
const resp = await fetch(
`${AUTH_URL}/auth/v1/token?grant_type=refresh_token`,
{
method: "POST",
headers: {
apikey: AUTH_PUBLIC_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ refresh_token: refreshToken }),
}
);
const { access_token } = await resp.json();
return access_token;
}
NEW_TOKEN=$(curl -s -X POST \
"${AUTH_URL}/auth/v1/token?grant_type=refresh_token" \
-H "apikey: ${AUTH_PUBLIC_KEY}" \
-H "Content-Type: application/json" \
-d "{\"refresh_token\":\"${REFRESH_TOKEN}\"}" \
| jq -r '.access_token')
def refresh_access_token(refresh_token)
uri = URI("#{AUTH_URL}/auth/v1/token?grant_type=refresh_token")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req['apikey'] = AUTH_PUBLIC_KEY
req['Content-Type'] = 'application/json'
req.body = JSON.dump(refresh_token: refresh_token)
resp = http.request(req)
JSON.parse(resp.body)['access_token']
end
Armazene o refresh_token de forma segura (variável de ambiente ou secret manager). Nunca exponha tokens em logs ou código fonte.
Roles
O token carrega um campo de role que define o que o usuário pode acessar dentro da sua empresa (tenant):
| Role | Acesso |
|---|---|
company_owner | Acesso total à empresa: entregas, motoristas, preços, assinatura/billing |
company_admin | Gestão operacional: entregas, motoristas, preços — sem acesso a billing |
driver | Aceitar/iniciar/completar entregas vinculadas, acessar própria carteira, atualizar posição GPS |
Chamar um endpoint com role insuficiente retorna 403 Forbidden. Veja Erros & Status para detalhes.
Endpoints públicos (sem autenticação)
| Endpoint | Descrição |
|---|---|
GET /health | Health check |
POST /api/v1/companies/register | Cadastro público de empresa |
POST /api/v1/webhooks/asaas/{company_id} | Receber eventos de pagamento/saque da sua empresa (usa assinatura HMAC-SHA256 no header asaas-signature) |