Skip to content

Referência da API

Documentação completa de todos os endpoints FastAPI do fast_deliv.

Base URL: https://fast-deliv-backend.vercel.app (produção) | http://localhost:8000 (dev)

Todos os endpoints (exceto /health) requerem autenticação via Bearer token JWT do Supabase.


Autenticação

Obter Token JWT

curl -X POST \
  "https://<PROJECT>.supabase.co/auth/v1/token?grant_type=password" \
  -H "apikey: <SUPABASE_ANON_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@example.com", "password": "senha123"}'

Resposta:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 3600
}

Use o access_token em todas as requisições:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...


Health Check

GET /health

Verifica se o servidor está operacional. Não requer autenticação.

curl http://localhost:8000/health

Resposta 200 OK:

{"status": "ok"}


Entregas (/api/v1/deliveries)

POST /api/v1/deliveries — Criar Entrega

Role: admin

Cria uma nova entrega. O backend calcula automaticamente a rota (via ORS) e o ganho do motorista.

curl -X POST http://localhost:8000/api/v1/deliveries \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Entrega Farmácia Central",
    "description": "Medicamentos urgentes",
    "origin_address": "Rua das Flores, 123 - Centro",
    "origin_lat": -23.550520,
    "origin_lng": -46.633308,
    "destination_address": "Av. Paulista, 1000 - Bela Vista",
    "destination_lat": -23.561684,
    "destination_lng": -46.655981,
    "client_value": 35.00,
    "notes": "Ligar antes de chegar"
  }'

Resposta 201 Created:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "title": "Entrega Farmácia Central",
  "description": "Medicamentos urgentes",
  "origin_address": "Rua das Flores, 123 - Centro",
  "origin_lat": -23.5505200,
  "origin_lng": -46.6333080,
  "destination_address": "Av. Paulista, 1000 - Bela Vista",
  "destination_lat": -23.5616840,
  "destination_lng": -46.6559810,
  "distance_km": 3.47,
  "route_polyline": "mflpDprwhGx...",
  "base_fare": 15.00,
  "price_per_km": 2.00,
  "min_km": 5.00,
  "driver_earning": 15.00,
  "client_value": 35.00,
  "company_profit": 20.00,
  "status": "pending",
  "driver_id": null,
  "created_by": "admin-uuid",
  "created_at": "2026-05-18T10:00:00Z",
  "wait_since": "2026-05-18T10:00:00Z",
  "assigned_at": null,
  "started_at": null,
  "completed_at": null,
  "notes": "Ligar antes de chegar"
}

Erros possíveis: - 400 — Campos obrigatórios faltando - 401 — Token inválido - 403 — Role não é admin - 502 — Falha ao calcular rota (ORS indisponível)


GET /api/v1/deliveries — Listar Entregas

Role: admin

Retorna todas as entregas ordenadas por created_at DESC.

curl http://localhost:8000/api/v1/deliveries \
  -H "Authorization: Bearer $TOKEN"

Resposta 200 OK: Array de DeliveryOut (mesma estrutura do POST).


PATCH /api/v1/deliveries/{id}/assign — Aceitar Entrega

Role: driver

Driver aceita uma entrega pending. Transição: pending → assigned.

curl -X PATCH \
  http://localhost:8000/api/v1/deliveries/550e8400-e29b-41d4-a716-446655440000/assign \
  -H "Authorization: Bearer $DRIVER_TOKEN"

Resposta 200 OK: DeliveryOut com status: "assigned" e driver_id preenchido.

Erros possíveis: - 404 — Entrega não encontrada - 422 — Transição inválida (entrega não está pending)


PATCH /api/v1/deliveries/{id}/start — Iniciar Coleta

Role: driver

Driver confirma que coletou o pacote. Transição: assigned → in_progress.

curl -X PATCH \
  http://localhost:8000/api/v1/deliveries/550e8400-e29b-41d4-a716-446655440000/start \
  -H "Authorization: Bearer $DRIVER_TOKEN"

Resposta 200 OK: DeliveryOut com status: "in_progress" e started_at preenchido.


PATCH /api/v1/deliveries/{id}/complete — Finalizar Entrega

Role: driver

Driver confirma entrega realizada. Transição: in_progress → completed.

Além de atualizar o status, automaticamente: 1. Insere registro em transactions (earning, credit) 2. Incrementa saldo em wallets via RPC PostgreSQL

curl -X PATCH \
  http://localhost:8000/api/v1/deliveries/550e8400-e29b-41d4-a716-446655440000/complete \
  -H "Authorization: Bearer $DRIVER_TOKEN"

Resposta 200 OK: DeliveryOut com status: "completed" e completed_at preenchido.


PATCH /api/v1/deliveries/{id}/cancel — Cancelar Entrega

Role: admin

Admin cancela uma entrega. Válido a partir de qualquer estado exceto completed e cancelled.

curl -X PATCH \
  http://localhost:8000/api/v1/deliveries/550e8400-e29b-41d4-a716-446655440000/cancel \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Resposta 200 OK: DeliveryOut com status: "cancelled".


Carteiras (/api/v1/wallets)

GET /api/v1/wallets/me — Ver Minha Carteira

Role: driver

Retorna o saldo atual da carteira do driver autenticado.

curl http://localhost:8000/api/v1/wallets/me \
  -H "Authorization: Bearer $DRIVER_TOKEN"

Resposta 200 OK:

{
  "driver_id": "driver-uuid",
  "balance": 145.50,
  "updated_at": "2026-05-18T09:30:00Z"
}


GET /api/v1/wallets/me/transactions — Histórico de Transações

Role: driver

Retorna as últimas 50 transações (ganhos, saques, ajustes).

curl http://localhost:8000/api/v1/wallets/me/transactions \
  -H "Authorization: Bearer $DRIVER_TOKEN"

Resposta 200 OK:

[
  {
    "id": "txn-uuid",
    "driver_id": "driver-uuid",
    "delivery_id": "delivery-uuid",
    "type": "earning",
    "amount": 29.00,
    "direction": "credit",
    "status": "completed",
    "description": "Ganho entrega #550e8400",
    "created_at": "2026-05-18T09:00:00Z"
  }
]


POST /api/v1/wallets/withdraw — Solicitar Saque

Role: driver

Cria uma solicitação de saque via Pix. O sistema verifica o saldo e inicia a transferência ASAAS.

curl -X POST http://localhost:8000/api/v1/wallets/withdraw \
  -H "Authorization: Bearer $DRIVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100.00,
    "pix_key": "11999999999",
    "pix_key_type": "PHONE"
  }'

Tipos de chave Pix aceitos: CPF, CNPJ, EMAIL, PHONE, EVP

Resposta 201 Created:

{
  "id": "withdrawal-uuid",
  "driver_id": "driver-uuid",
  "amount": 100.00,
  "pix_key": "11999999999",
  "pix_key_type": "PHONE",
  "status": "pending",
  "asaas_transfer_id": "tra_000012345",
  "requested_at": "2026-05-18T10:00:00Z",
  "completed_at": null,
  "error_message": null
}

Erros possíveis: - 404 — Carteira não encontrada - 422 — Saldo insuficiente - 502 — Falha na transferência ASAAS


Localização (/api/v1/locations)

PUT /api/v1/locations/me — Atualizar Localização

Role: driver

Upsert da localização GPS do driver. Chamado pelo PWA a cada 10 segundos quando online.

curl -X PUT http://localhost:8000/api/v1/locations/me \
  -H "Authorization: Bearer $DRIVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "lat": -23.550520,
    "lng": -46.633308,
    "heading": 180.0,
    "speed": 35.5,
    "accuracy": 12.3,
    "delivery_id": "550e8400-e29b-41d4-a716-446655440000",
    "is_online": true
  }'

Resposta 204 No Content


GET /api/v1/locations — Listar Localizações dos Drivers

Role: admin

Retorna a localização atual de todos os drivers online.

curl http://localhost:8000/api/v1/locations \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Resposta 200 OK:

[
  {
    "driver_id": "driver-uuid",
    "lat": -23.550520,
    "lng": -46.633308,
    "heading": 180.0,
    "speed": 35.5,
    "accuracy": 12.3,
    "delivery_id": "550e8400-e29b-41d4-a716-446655440000",
    "is_online": true,
    "updated_at": "2026-05-18T10:05:00Z"
  }
]


Motoristas (/api/v1/drivers)

GET /api/v1/drivers — Listar Motoristas

Role: admin

Retorna todos os motoristas com informações de perfil e saldo.

curl http://localhost:8000/api/v1/drivers \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Resposta 200 OK:

[
  {
    "driver_id": "driver-uuid",
    "full_name": "João Silva",
    "phone": "11999999999",
    "is_active": true,
    "balance": 145.50,
    "updated_at": "2026-05-18T09:30:00Z"
  }
]


Configuração de Preço (/api/v1/pricing)

GET /api/v1/pricing — Obter Configuração Atual

Role: admin

Retorna a configuração de preço mais recente.

curl http://localhost:8000/api/v1/pricing \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Resposta 200 OK:

{
  "id": "pricing-uuid",
  "base_fare": 15.00,
  "price_per_km": 2.00,
  "min_km": 5.00,
  "updated_at": "2026-05-18T00:00:00Z",
  "updated_by": "admin-uuid"
}


PUT /api/v1/pricing — Atualizar Configuração de Preço

Role: admin

Insere nova configuração de preço (mantém histórico).

curl -X PUT http://localhost:8000/api/v1/pricing \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "base_fare": 18.00,
    "price_per_km": 2.50,
    "min_km": 5.00
  }'

Resposta 200 OK: Nova PricingConfigOut.


Webhooks (/api/v1/webhooks)

POST /api/v1/webhooks/asaas — Webhook ASAAS

Endpoint para receber notificações de transferências do ASAAS. Não requer autenticação JWT, mas valida a assinatura HMAC-SHA256 no header asaas-signature.

Eventos processados: - TRANSFER_DONE / TRANSFER_APPROVED → atualiza withdrawal.status = 'completed' - TRANSFER_FAILED / TRANSFER_CANCELLED → atualiza withdrawal.status = 'failed'

# Simulação de webhook (para testes)
BODY='{"event":"TRANSFER_DONE","transfer":{"id":"tra_000012345"}}'
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$ASAAS_WEBHOOK_SECRET" | awk '{print $2}')

curl -X POST http://localhost:8000/api/v1/webhooks/asaas \
  -H "Content-Type: application/json" \
  -H "asaas-signature: $SIGNATURE" \
  -d "$BODY"

Resposta 200 OK:

{"status": "ok"}


Schemas de Dados

DeliveryCreate (request)

class DeliveryCreate(BaseModel):
    title: str                          # min_length=1, max_length=200
    description: str | None = None
    origin_address: str
    origin_lat: Decimal
    origin_lng: Decimal
    destination_address: str
    destination_lat: Decimal
    destination_lng: Decimal
    client_value: Decimal | None = None
    notes: str | None = None

WithdrawalRequest (request)

class WithdrawalRequest(BaseModel):
    amount: Decimal    # gt=0
    pix_key: str       # min_length=1
    pix_key_type: Literal["CPF", "CNPJ", "EMAIL", "PHONE", "EVP"]

LocationUpdate (request)

class LocationUpdate(BaseModel):
    lat: Decimal
    lng: Decimal
    heading: Decimal | None = None
    speed: Decimal | None = None
    accuracy: Decimal | None = None
    delivery_id: str | None = None
    is_online: bool = True

Códigos de Erro

Código Significado
400 Dados de entrada inválidos
401 Token ausente, inválido ou expirado
403 Role insuficiente para o endpoint
404 Recurso não encontrado
422 Transição de status inválida ou saldo insuficiente
502 Falha em serviço externo (ASAAS ou ORS)