Gestor Urbano

Documentação da API
Visualizador Status

API Cata-Bagulho

Servidor REST para entrega dos JSONs de Cata-Bagulho conforme o DIS PRODAM v1.1. Autenticação por usuário e senha; cadeia de partes via campo proximoArquivo.

01Visão geral

Esta API entrega os pontos atendidos pelo serviço de Cata-Bagulho. Os dados são organizados como setores → logradouros → trechos → coordenadas, conforme o DIS PRODAM v1.1.

Convenções

  • Base URL: https://prodam.gestorurbano.com.br
  • Método HTTP: GET (somente leitura)
  • Formato: application/json (UTF-8)
  • Autenticação: usuário e senha (HTTP Basic)
  • HTTPS: obrigatório (HTTP é redirecionado com 308)
Importante: cada cliente vê apenas os próprios dados. O par usuário/senha identifica a empresa.

02Autenticação

A API usa autenticação HTTP padrão. Você passa usuário e senha em cada requisição — qualquer cliente HTTP moderno já tem suporte nativo, sem você precisar construir nada manualmente.

Onde informar

ClienteComo passar usuário e senha
cURL curl -u "usuario:senha" https://...
Python (requests) requests.get(url, auth=("usuario", "senha"))
JavaScript / Node Header Authorization: Basic ... (o btoa/Buffer faz a codificação)
Postman / Insomnia / Bruno Aba Auth → tipo Basic Auth → preencha usuário e senha
Browser O navegador exibe um popup pedindo usuário e senha automaticamente
Importante: a credencial precisa ser enviada em toda chamada (não há sessão/cookie). Bibliotecas HTTP cuidam disso automaticamente quando você usa session.auth ou equivalente. As credenciais nos exemplos abaixo (usuario/senha) são apenas placeholders — use as suas reais.

03Endpoint

O servidor expõe um único padrão de URL, com o nome do arquivo no path:

GET /{empresa}/{servico}/json/{filename}
A primeira chamada usa o arquivo inicial; as próximas usam o nome indicado em detalheArquivo.proximoArquivo da resposta anterior.

Parâmetros do path

ParâmetroExemploDescrição
empresaempresa Identificador da concessionária (corresponde ao usuário do Basic Auth)
servicocata_bagulho Nome do serviço (atualmente apenas cata_bagulho)
filenamecata_bagulho_empresa.json (parte 1)
cata_bagulho_empresa_2.json (parte 2)
cata_bagulho_empresa_N.json (parte N)
Nome do arquivo da parte solicitada. O cliente sempre começa pelo arquivo inicial (sem sufixo _N) e segue o proximoArquivo retornado.

Exemplos de URL

# Parte 1 (sempre o arquivo inicial)
GET /empresa/cata_bagulho/json/cata_bagulho_empresa.json

# Parte 2 (informado em proximoArquivo da parte 1)
GET /empresa/cata_bagulho/json/cata_bagulho_empresa_2.json

# Parte N (continua seguindo a cadeia ate proximoArquivo = "Final")
GET /empresa/cata_bagulho/json/cata_bagulho_empresa_N.json

04Cadeia de partes

Quando o conjunto de dados é grande, ele é dividido em várias partes. Cada parte tem no final do JSON o campo detalheArquivo.proximoArquivo, que indica o nome literal do próximo arquivo a buscar.

{
  "empresas": [ ... ],
  "detalheArquivo": {
    "qtdeSetores": 25,
    "proximoArquivo": "cata_bagulho_empresa_2.json"
  }
}

O cliente continua iterando até que proximoArquivo seja a string literal "Final":

# Pseudocodigo do fluxo
atual = "cata_bagulho_empresa.json"
todas_partes = []

while atual != "Final":
    resposta = GET "/empresa/cata_bagulho/json/" + atual
    todas_partes.append(resposta.json())
    atual = resposta.json()["detalheArquivo"]["proximoArquivo"]

05Schema do JSON

Conforme o DIS PRODAM v1.1. A raiz tem um array empresas (cada item é um setor) e o metadado detalheArquivo.

Setor (item do array empresas)

CampoTipoDescrição
idstringIdentificador único do setor
codigoSetorstringCódigo (ex: AA10500GO0001)
subprefeiturastringNome da subprefeitura
frequenciastringDiário, Semanal, Bissemanal, Mensal, etc
horarioInicialstringFormato HH:MM
horarioFinalstringFormato HH:MM
diasarray<string>Datas YYYY-MM-DD em ordem cronológica
servicostringSempre "cata_bagulho"
empresastringNome da concessionária
logradourosarray<Logradouro>Lista de vias atendidas

Logradouro

CampoTipoDescrição
logradourostringNome da via
latitudenumberLatitude representativa
longitudenumberLongitude representativa
cepstringCEP no formato 00000-000
trechosarray<Trecho>Segmentos atendidos

Trecho

CampoTipoDescrição
idstringIdentificador único do trecho
enderecoInicialstringEndereço de início
enderecoFinalstringEndereço de término
coordenadasarray<Coord>Pontos da polyline

Coordenada

CampoTipoDescrição
latitudenumberLatitude em graus decimais
longitudenumberLongitude em graus decimais

detalheArquivo (raiz)

CampoTipoDescrição
qtdeSetoresintegerQuantidade de setores no arquivo
proximoArquivostringNome do próximo arquivo ou "Final"

Modelo montado (exemplo)

Como uma parte fica quando montada — 1 setor resumido (na prática o array empresas traz vários setores por arquivo):

{
  "empresas": [
    {
      "id": "1",
      "codigoSetor": "AA10500GO0001",
      "subprefeitura": "Subprefeitura Exemplo",
      "frequencia": "Quinzenal",
      "horarioInicial": "06:00",
      "horarioFinal": "14:20",
      "dias": ["2026-03-16", "2026-03-30"],
      "servico": "cata_bagulho",
      "empresa": "Concessionária Exemplo",
      "logradouros": [
        {
          "logradouro": "Rua Exemplo",
          "latitude": -23.603269,
          "longitude": -46.779871,
          "cep": "08490-000",
          "trechos": [
            {
              "id": "1",
              "enderecoInicial": "Rua A",
              "enderecoFinal": "Rua B",
              "coordenadas": [
                { "latitude": -23.603225, "longitude": -46.780112 },
                { "latitude": -23.603248, "longitude": -46.779987 }
              ]
            }
          ]
        }
      ]
    }
  ],
  "detalheArquivo": {
    "qtdeSetores": 25,
    "proximoArquivo": "cata_bagulho_empresa_2.json"
  }
}

06Exemplos de código

Selecione a linguagem ou ferramenta. Substitua empresa, usuario e senha pelos seus valores reais.

# Uma parte
curl -u "usuario:senha" \
  https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json/cata_bagulho_empresa.json

# Cadeia completa (script bash com jq)
URL="https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json"
ARQ="cata_bagulho_empresa.json"
while [ "$ARQ" != "Final" ] && [ -n "$ARQ" ]; do
  echo "Baixando $ARQ..."
  RESP=$(curl -s -u "usuario:senha" "$URL/$ARQ")
  echo "$RESP" > "$ARQ"
  ARQ=$(echo "$RESP" | jq -r '.detalheArquivo.proximoArquivo')
done
# Com a biblioteca requests (recomendado)
import requests

BASE = "https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json"
AUTH = ("usuario", "senha")

session = requests.Session()
session.auth = AUTH

atual = "cata_bagulho_empresa.json"
todas = []
while atual and atual.lower() != "final":
    r = session.get(f"{BASE}/{atual}", timeout=60)
    r.raise_for_status()
    data = r.json()
    todas.append(data)
    atual = data["detalheArquivo"]["proximoArquivo"]

print(f"Baixei {len(todas)} parte(s)")

Sem dependências externas (stdlib)

import json
from urllib import request
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener

BASE = "https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json"

pm = HTTPPasswordMgrWithDefaultRealm()
pm.add_password(None, BASE, "usuario", "senha")
opener = build_opener(HTTPBasicAuthHandler(pm))

def baixar(arquivo):
    with opener.open(f"{BASE}/{arquivo}", timeout=60) as r:
        return json.loads(r.read())

atual = "cata_bagulho_empresa.json"
todas = []
while atual and atual.lower() != "final":
    data = baixar(atual)
    todas.append(data)
    atual = data["detalheArquivo"]["proximoArquivo"]
// Fetch nativo do navegador
const BASE = "https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json";
const AUTH = "Basic " + btoa("usuario:senha");

async function baixar(arquivo) {
  const r = await fetch(`${BASE}/${arquivo}`, {
    headers: { "Authorization": AUTH }
  });
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
  return r.json();
}

let atual = "cata_bagulho_empresa.json";
const todas = [];
while (atual && atual.toLowerCase() !== "final") {
  const data = await baixar(atual);
  todas.push(data);
  atual = data.detalheArquivo.proximoArquivo;
}
console.log(`${todas.length} parte(s) baixadas`);
// Node.js 18+ (fetch nativo)
const BASE = "https://prodam.gestorurbano.com.br/empresa/cata_bagulho/json";
const AUTH = "Basic " + Buffer.from("usuario:senha").toString("base64");

async function baixarTudo() {
  let atual = "cata_bagulho_empresa.json";
  const todas = [];

  while (atual && atual.toLowerCase() !== "final") {
    const r = await fetch(`${BASE}/${atual}`, {
      headers: { Authorization: AUTH }
    });
    if (!r.ok) throw new Error(`HTTP ${r.status} em ${atual}`);

    const lastModified = r.headers.get("Last-Modified");
    const data = await r.json();
    todas.push({ arquivo: atual, lastModified, data });
    atual = data.detalheArquivo?.proximoArquivo;
  }
  return todas;
}

baixarTudo().then(p => console.log(`Baixei ${p.length} parte(s)`));

07Códigos de retorno

StatusSignificadoO que fazer
200 Sucesso. JSON retornado no body. Processe normalmente. Header Last-Modified indica a última atualização.
400 {"erro": "ultimo arquivo foi o parte N"} — fim da cadeia. Pare de iterar. Você já tem todas as partes.
401 Credenciais ausentes ou inválidas. Confira usuário e senha.
403 Autenticou, mas não pode acessar essa empresa/serviço. Use as credenciais da empresa correta.
404 Empresa ou serviço não cadastrado no servidor. Verifique o path da URL.
429 Rate limit atingido (excesso de falhas de autenticação). Aguarde 1 hora ou contate o suporte.

08Rate limits e desempenho

  • 60 requisições / minuto por IP em endpoints de dados
  • 20 falhas de autenticação / hora por IP → bloqueio temporário
  • Tamanho típico de uma parte: 500 KB a 3,5 MB
  • Tamanho típico de uma cadeia completa: 1 a 10 MB
Recomendação: a PRODAM costuma consumir os dados uma vez por ano (conforme o DIS). Você pode cachear o conteúdo localmente e usar o header Last-Modified para decidir se vale a pena re-baixar.

09Suporte e ferramentas

Especificação oficial: DIS - Integração CataBagulho JSON - PRODAM v1.1 (07/03/2025).