Skip to content

Localizacao em Tempo Real


PUT /api/v1/locations/me

Motorista atualiza sua posicao GPS. Deve ser chamado periodicamente durante a entrega.

Auth: Bearer token — role driver

Rate limit: maximo 1 requisicao a cada 10 segundos por motorista.

Request body

Campo Tipo Obrigatorio Descricao
lat float sim Latitude atual
lng float sim Longitude atual
heading float nao Direcao em graus (0-360)
speed_kmh float nao Velocidade em km/h

Response 200 OK

{
  "driver_id": "550e8400-e29b-41d4-a716-446655440001",
  "lat": -16.6869,
  "lng": -49.2648,
  "heading": 180.0,
  "speed_kmh": 35.5,
  "updated_at": "2026-05-19T14:30:00Z"
}
import requests
import time

BASE_URL = "https://fast-deliv-backend.vercel.app"
headers = {"Authorization": f"Bearer {TOKEN}"}

def update_location(lat: float, lng: float, heading: float = None):
    payload = {"lat": lat, "lng": lng}
    if heading is not None:
        payload["heading"] = heading

    resp = requests.put(
        f"{BASE_URL}/api/v1/locations/me",
        headers=headers,
        json=payload,
    )
    resp.raise_for_status()
    return resp.json()

# Loop de atualizacao (respeita o rate limit de 10s)
while True:
    loc = update_location(-16.6869, -49.2648, heading=90.0)
    print(f"Posicao atualizada: {loc['updated_at']}")
    time.sleep(10)
async function updateLocation(lat, lng, heading = null) {
  const body = { lat, lng };
  if (heading !== null) body.heading = heading;

  const resp = await fetch(`${BASE_URL}/api/v1/locations/me`, {
    method: "PUT",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  return resp.json();
}

// Usando Geolocation API do browser
function startTracking() {
  setInterval(() => {
    navigator.geolocation.getCurrentPosition(async (pos) => {
      const loc = await updateLocation(
        pos.coords.latitude,
        pos.coords.longitude,
        pos.coords.heading
      );
      console.log("Posicao atualizada:", loc.updated_at);
    });
  }, 10000); // a cada 10s
}
# Atualizar posicao uma vez
curl -s -X PUT "${BASE_URL}/api/v1/locations/me" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"lat": -16.6869, "lng": -49.2648, "heading": 90.0}' \
  | jq '{updated_at}'
def update_location(token, lat, lng, heading: nil)
  uri = URI("#{BASE_URL}/api/v1/locations/me")
  req = Net::HTTP::Put.new(uri)
  req['Authorization'] = "Bearer #{token}"
  req['Content-Type'] = 'application/json'
  payload = { lat: lat, lng: lng }
  payload[:heading] = heading if heading
  req.body = JSON.dump(payload)

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  JSON.parse(http.request(req).body)
end

GET /api/v1/locations

Lista a ultima localizacao conhecida de todos os motoristas ativos.

Auth: Bearer token — role admin

Response 200 OK

Array de objetos de localizacao:

Campo Tipo Descricao
driver_id UUID ID do motorista
driver_name string Nome do motorista
lat float Ultima latitude conhecida
lng float Ultima longitude conhecida
heading float ou null Direcao em graus
speed_kmh float ou null Velocidade
updated_at datetime Horario da ultima atualizacao
resp = requests.get(f"{BASE_URL}/api/v1/locations", headers=headers)
locations = resp.json()

for loc in locations:
    age_min = (now - parse_datetime(loc["updated_at"])).seconds // 60
    print(f"{loc['driver_name']}: {loc['lat']},{loc['lng']} (ha {age_min} min)")
const resp = await fetch(`${BASE_URL}/api/v1/locations`, { headers });
const locations = await resp.json();

locations.forEach((loc) => {
  const ageMs = Date.now() - new Date(loc.updated_at).getTime();
  const ageMin = Math.floor(ageMs / 60000);
  console.log(`${loc.driver_name}: ${loc.lat},${loc.lng} (ha ${ageMin} min)`);
});
curl -s "${BASE_URL}/api/v1/locations" \
  -H "Authorization: Bearer ${TOKEN}" \
  | jq '.[] | {driver_name, lat, lng, updated_at}'
uri = URI("#{BASE_URL}/api/v1/locations")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
locations = JSON.parse(http.request(req).body)

locations.each do |loc|
  puts "#{loc['driver_name']}: #{loc['lat']},#{loc['lng']}"
end

Rastreamento em tempo real via Supabase Realtime

Para receber atualizacoes de posicao em tempo real sem polling, use Supabase Realtime com o canal driver_locations.

Supabase Realtime

Este canal usa o mecanismo de Broadcast do Supabase. Voce precisa da URL e da anon key do Supabase (nao do backend fast_deliv).

import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  "https://<PROJECT>.supabase.co",
  "<ANON_KEY>"
);

// Ouvir atualizacoes de todos os motoristas
const channel = supabase
  .channel("driver_locations")
  .on(
    "postgres_changes",
    {
      event: "UPDATE",
      schema: "public",
      table: "driver_locations",
    },
    (payload) => {
      const { driver_id, lat, lng, heading, updated_at } = payload.new;
      console.log(`Motorista ${driver_id}: ${lat}, ${lng}`);
      // Atualize o marcador no mapa aqui
    }
  )
  .subscribe();

// Para parar de ouvir
// await supabase.removeChannel(channel);

Performance

Para dashboards com muitos motoristas, filtre por driver_id para reduzir o volume de eventos:

.on("postgres_changes", {
  event: "UPDATE",
  schema: "public",
  table: "driver_locations",
  filter: `driver_id=eq.${DRIVER_ID}`,
}, handler)