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)
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
| Cliente | Como 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 |
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:
detalheArquivo.proximoArquivo da resposta anterior.Parâmetros do path
| Parâmetro | Exemplo | Descrição |
|---|---|---|
empresa | empresa |
Identificador da concessionária (corresponde ao usuário do Basic Auth) |
servico | cata_bagulho |
Nome do serviço (atualmente apenas cata_bagulho) |
filename | cata_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)
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador único do setor |
codigoSetor | string | Código (ex: AA10500GO0001) |
subprefeitura | string | Nome da subprefeitura |
frequencia | string | Diário, Semanal, Bissemanal, Mensal, etc |
horarioInicial | string | Formato HH:MM |
horarioFinal | string | Formato HH:MM |
dias | array<string> | Datas YYYY-MM-DD em ordem cronológica |
servico | string | Sempre "cata_bagulho" |
empresa | string | Nome da concessionária |
logradouros | array<Logradouro> | Lista de vias atendidas |
Logradouro
| Campo | Tipo | Descrição |
|---|---|---|
logradouro | string | Nome da via |
latitude | number | Latitude representativa |
longitude | number | Longitude representativa |
cep | string | CEP no formato 00000-000 |
trechos | array<Trecho> | Segmentos atendidos |
Trecho
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador único do trecho |
enderecoInicial | string | Endereço de início |
enderecoFinal | string | Endereço de término |
coordenadas | array<Coord> | Pontos da polyline |
Coordenada
| Campo | Tipo | Descrição |
|---|---|---|
latitude | number | Latitude em graus decimais |
longitude | number | Longitude em graus decimais |
detalheArquivo (raiz)
| Campo | Tipo | Descrição |
|---|---|---|
qtdeSetores | integer | Quantidade de setores no arquivo |
proximoArquivo | string | Nome 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
| Status | Significado | O 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
Last-Modified
para decidir se vale a pena re-baixar.
09Suporte e ferramentas
- Visualizador público — login com sua credencial, vê os JSONs no mapa
- Status da API — página de uptime e healthcheck visual
Especificação oficial: DIS - Integração CataBagulho JSON - PRODAM v1.1 (07/03/2025).