{"openapi":"3.1.0","info":{"title":"API MobiCidades","version":"1.0.0","description":"API pública do MobiCidades para integração com o órgão gestor da mobilidade urbana\nde Teresina/PI.\n\n**Autenticação.** Toda requisição exige uma chave de API no cabeçalho `X-API-Key`\n(ou `Authorization: Bearer <chave>`). As chaves são emitidas no Portal do Gestor,\nem *Integração e API*, com escopos e limite de requisições por minuto.\n\n**Escopos.** `ocorrencias:ler`, `ocorrencias:atender`, `ocorrencias:escrever`,\n`linhas:ler`, `estatisticas:ler`.\n\n**Webhooks.** O sistema também envia eventos (`ocorrencia.criada`, `ocorrencia.status_alterado`,\n`ocorrencia.resolvida`) para uma URL do órgão, assinados em HMAC-SHA256 no cabeçalho\n`X-Chego-Assinatura`, no formato `t=<unix>,v1=<hex>` sobre `<t>.<corpo>`.","contact":{"name":"MobiCidades","email":"contato@mobicidades.com.br"},"license":{"name":"Dados abertos","url":"https://0.0.0.0:3000/dados-abertos"}},"servers":[{"url":"https://0.0.0.0:3000/api/v1","description":"Produção"}],"security":[{"ChaveApi":[]}],"components":{"securitySchemes":{"ChaveApi":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Ocorrencia":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"protocolo":{"type":"string","example":"MC-2026-000123"},"status":{"type":"string","enum":["nova","triagem","encaminhada","em_atendimento","resolvida","improcedente","duplicada"]},"severidade":{"type":"string","enum":["baixa","media","alta","critica"]},"descricao":{"type":"string","nullable":true},"endereco":{"type":"string","nullable":true},"bairro":{"type":"string","nullable":true},"veiculo_prefixo":{"type":"string","nullable":true},"confirmacoes":{"type":"integer","description":"Quantas outras pessoas confirmaram o mesmo problema."},"criada_em":{"type":"string","format":"date-time"},"prazo_sla":{"type":"string","format":"date-time","nullable":true},"resolvida_em":{"type":"string","format":"date-time","nullable":true},"resolucao":{"type":"string","nullable":true},"protocolo_externo":{"type":"string","nullable":true,"description":"Protocolo no sistema do órgão gestor."},"sla_estourado":{"type":"boolean"},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"tipo":{"type":"object","properties":{"slug":{"type":"string"},"nome":{"type":"string"}}},"linha":{"type":"object","nullable":true,"properties":{"codigo":{"type":"string"},"nome":{"type":"string"}}},"empresa":{"type":"string","nullable":true}}},"Erro":{"type":"object","properties":{"ok":{"type":"boolean","example":false},"erro":{"type":"string"},"detalhes":{"type":"array","items":{"type":"object"},"nullable":true}}}},"responses":{"NaoAutorizado":{"description":"Chave ausente, inválida ou revogada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"SemEscopo":{"description":"A chave não tem o escopo necessário.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"LimiteExcedido":{"description":"Limite de requisições por minuto atingido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}}}},"paths":{"/ocorrencias":{"get":{"summary":"Listar ocorrências","description":"Lista as ocorrências do órgão vinculado à chave, mais recentes primeiro. Use `sla=vencidas` para a fila crítica.","tags":["Ocorrências"],"parameters":[{"name":"status","in":"query","schema":{"type":"string"},"description":"Lista separada por vírgula."},{"name":"tipo","in":"query","schema":{"type":"string"},"description":"Slugs separados por vírgula."},{"name":"linha","in":"query","schema":{"type":"string"},"description":"Código da linha."},{"name":"bairro","in":"query","schema":{"type":"string"}},{"name":"desde","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"ate","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"sla","in":"query","schema":{"type":"string","enum":["vencidas","no_prazo"]}},{"name":"pagina","in":"query","schema":{"type":"integer","default":1}},{"name":"por_pagina","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Lista paginada.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"dados":{"type":"array","items":{"$ref":"#/components/schemas/Ocorrencia"}},"meta":{"type":"object","nullable":true}}}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"403":{"$ref":"#/components/responses/SemEscopo"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}},"post":{"summary":"Registrar ocorrência de outro canal","description":"Permite que o órgão registre no mapa público uma demanda que chegou pela ouvidoria, telefone ou atendimento presencial. Requer o escopo `ocorrencias:escrever`.","tags":["Ocorrências"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tipo"],"properties":{"tipo":{"type":"string","example":"quebrado"},"linha_codigo":{"type":"string","example":"0203"},"veiculo_prefixo":{"type":"string","example":"1234"},"descricao":{"type":"string"},"latitude":{"type":"number","example":-5.0892},"longitude":{"type":"number","example":-42.8019},"endereco":{"type":"string"},"bairro":{"type":"string"},"protocolo_externo":{"type":"string","example":"2026/0001234"}}}}}},"responses":{"201":{"description":"Ocorrência criada (ou agrupada a uma equivalente).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"dados":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"protocolo":{"type":"string"},"agrupada_em":{"type":"string","nullable":true}}},"meta":{"type":"object","nullable":true}}}}}},"422":{"description":"Dados inválidos."}}}},"/ocorrencias/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"UUID ou protocolo (ex.: MC-2026-000123)."}],"get":{"summary":"Detalhar ocorrência","description":"Devolve a ocorrência com toda a trilha de atendimento, inclusive notas internas do órgão.","tags":["Ocorrências"],"responses":{"200":{"description":"Detalhe da ocorrência.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"dados":{"$ref":"#/components/schemas/Ocorrencia"},"meta":{"type":"object","nullable":true}}}}}},"404":{"description":"Não encontrada."}}},"patch":{"summary":"Devolver andamento do atendimento","description":"É por aqui que o sistema do órgão gestor devolve o andamento: muda o status, publica a resposta oficial ao cidadão e amarra o protocolo interno. Requer o escopo `ocorrencias:atender`.","tags":["Ocorrências"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["triagem","em_atendimento","resolvida","improcedente"]},"resposta":{"type":"string","description":"Texto da resposta oficial ao cidadão."},"protocolo_externo":{"type":"string","example":"2026/0001234"},"sistema_externo":{"type":"string","example":"SIGEP"},"publicar_resposta":{"type":"boolean","default":true,"description":"Falso registra como nota interna, sem exibir ao cidadão."}}}}}},"responses":{"200":{"description":"Ocorrência atualizada.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"dados":{"$ref":"#/components/schemas/Ocorrencia"},"meta":{"type":"object","nullable":true}}}}}},"422":{"description":"Dados inválidos."}}}},"/linhas":{"get":{"summary":"Listar linhas","tags":["Cadastros"],"parameters":[{"name":"busca","in":"query","schema":{"type":"string"}},{"name":"ativas","in":"query","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Linhas com contagem de ocorrências."}}}},"/tipos":{"get":{"summary":"Listar tipos de ocorrência e prazos","tags":["Cadastros"],"responses":{"200":{"description":"Tipos ativos com o SLA de cada um."}}}},"/estatisticas":{"get":{"summary":"Indicadores agregados","tags":["Indicadores"],"parameters":[{"name":"dias","in":"query","schema":{"type":"integer","default":30,"maximum":365}}],"responses":{"200":{"description":"Resumo, série diária, ranking e desempenho de SLA."}}}}},"tags":[{"name":"Ocorrências","description":"Consulta e atendimento das ocorrências."},{"name":"Cadastros","description":"Linhas e tipos."},{"name":"Indicadores","description":"Dados agregados para dashboards."}]}