Autenticacao
A API usa JWT Bearer tokens emitidos pelo Supabase Auth. Toda requisicao (exceto /health e o webhook ASAAS) deve incluir o header Authorization.
Obtendo o token
Faca um POST diretamente na API do Supabase com email e senha:
import requests
SUPABASE_URL = "https://<PROJECT>.supabase.co"
SUPABASE_ANON_KEY = "<ANON_KEY>"
def get_token(email: str, password: str) -> str:
resp = requests.post(
f"{SUPABASE_URL}/auth/v1/token?grant_type=password",
headers={
"apikey": SUPABASE_ANON_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("admin@empresa.com", "senha123")
const SUPABASE_URL = "https://<PROJECT>.supabase.co";
const SUPABASE_ANON_KEY = "<ANON_KEY>";
async function getToken(email, password) {
const resp = await fetch(
`${SUPABASE_URL}/auth/v1/token?grant_type=password`,
{
method: "POST",
headers: {
apikey: SUPABASE_ANON_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 };
}
SUPABASE_URL="https://<PROJECT>.supabase.co"
SUPABASE_ANON_KEY="<ANON_KEY>"
AUTH_RESP=$(curl -s -X POST \
"${SUPABASE_URL}/auth/v1/token?grant_type=password" \
-H "apikey: ${SUPABASE_ANON_KEY}" \
-H "Content-Type: application/json" \
-d '{"email":"admin@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'
SUPABASE_URL = "https://<PROJECT>.supabase.co"
SUPABASE_ANON_KEY = "<ANON_KEY>"
def get_token(email, password)
uri = URI("#{SUPABASE_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'] = SUPABASE_ANON_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('admin@empresa.com', 'senha123')
Usando o token nas requisicoes
Inclua o token no header Authorization em todas as requisicoes autenticadas:
Expiracao e refresh
O token expira em 1 hora. Use o refresh_token para obter um novo access_token sem reautenticar:
def refresh_access_token(refresh_token: str) -> str:
resp = requests.post(
f"{SUPABASE_URL}/auth/v1/token?grant_type=refresh_token",
headers={
"apikey": SUPABASE_ANON_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(
`${SUPABASE_URL}/auth/v1/token?grant_type=refresh_token`,
{
method: "POST",
headers: {
apikey: SUPABASE_ANON_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ refresh_token: refreshToken }),
}
);
const { access_token } = await resp.json();
return access_token;
}
def refresh_access_token(refresh_token)
uri = URI("#{SUPABASE_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'] = SUPABASE_ANON_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
Boas praticas
Armazene o refresh_token de forma segura (variavel de ambiente ou secret manager). Nunca exponha tokens em logs ou codigo fonte.
Roles: admin vs driver
O JWT contem um campo user_metadata.role que define o que o usuario pode acessar:
| Role | Acesso |
|---|---|
admin |
Criar/listar/cancelar entregas, ver todos motoristas e localizacoes, gerenciar precos |
driver |
Aceitar/iniciar/completar entregas proprias, acessar propria carteira, atualizar GPS |
Acesso negado
Chamar um endpoint com role insuficiente retorna 403 Forbidden. Veja Erros & Status para detalhes.
Endpoints publicos (sem autenticacao)
| Endpoint | Descricao |
|---|---|
GET /health |
Health check |
POST /api/v1/webhooks/asaas |
Webhook ASAAS (usa HMAC-SHA256 no header asaas-signature) |