{
  "openapi": "3.1.0",
  "info": {
    "title": "API do Brasil Sintético",
    "version": "0.1.0",
    "description": "Simule campanhas numa população sintética do Brasil."
  },
  "servers": [
    {
      "url": "https://api.brasilsintetico.com"
    }
  ],
  "security": [
    {
      "projectKey": []
    }
  ],
  "paths": {
    "/v1/whoami": {
      "get": {
        "tags": [
          "Chave de API"
        ],
        "summary": "Quem sou eu",
        "operationId": "whoami",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhoAmI"
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas/cenario-campanha": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Schema do pedido de campanha",
        "description": "O JSON Schema do pedido de campanha (draft 2020-12), gerado do contrato. Público: um programa ou um agente o lê antes de enviar qualquer coisa.",
        "operationId": "scenario_schema",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/v1/jobs/estimate": {
      "post": {
        "tags": [
          "Jobs"
        ],
        "summary": "Cotar um job",
        "description": "Valida e cota um pedido sem reservar nada.",
        "operationId": "estimate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Request"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs": {
      "post": {
        "tags": [
          "Jobs"
        ],
        "summary": "Enviar um job",
        "operationId": "submit",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Request"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Listar os jobs",
        "operationId": "list_jobs",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/JobOut"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/compare": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Comparar dois jobs",
        "description": "Duas simulações concluídas do projeto, na mesma release, lado a lado: cada cenário e, tabela por tabela, os números principais dos achados com a diferença. Só se lê o que a rota dos achados serve, então a regra de privacidade vale.",
        "operationId": "compare_jobs",
        "parameters": [
          {
            "name": "a",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "O primeiro job"
            },
            "description": "O primeiro job"
          },
          {
            "name": "b",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "O segundo job: cada diferença é b menos a"
            },
            "description": "O segundo job: cada diferença é b menos a"
          },
          {
            "name": "municipio",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "description": "Códigos IBGE a manter; por padrão, os que uma das duas campanhas mira"
            },
            "description": "Códigos IBGE a manter; por padrão, os que uma das duas campanhas mira"
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComparisonOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Ler um job",
        "operationId": "get_job",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}/findings": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Ler uma tabela dos achados de um job",
        "description": "Os achados de um job concluído, em linhas: é assim que se lê a saída de um job.",
        "operationId": "get_findings",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tabela",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Uma de: `saturacao`, `alcance_efetivo`, `alcance_potencial`, `contribuicao`, `elasticidade`, `veredito`",
              "default": "saturacao"
            },
            "description": "Uma de: `saturacao`, `alcance_efetivo`, `alcance_potencial`, `contribuicao`, `elasticidade`, `veredito`"
          },
          {
            "name": "municipio",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "description": "Códigos IBGE a manter; por padrão, os municípios que a campanha mira"
            },
            "description": "Códigos IBGE a manter; por padrão, os municípios que a campanha mira"
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FindingsOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}/respostas": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Ler as respostas do contrato de resposta de um job",
        "description": "As respostas às perguntas que o contrato de resposta do job fez (`contrato_de_resposta`): calculadas por código a partir do que a simulação publicou, nunca de uma pessoa sintética, cada uma com uma frase. Uma resposta sobre setores censitários (uma lista, ou os que ficam no raio de um ponto) volta retida, com o motivo do corte, quando um deles não passa no corte de erro do diagnóstico. Um job sem contrato responde uma lista vazia.",
        "operationId": "get_answers",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnswersOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}/setores": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Ler os eventos de um job por setor censitário e semana",
        "description": "Os eventos de um município por setor censitário e semana, para um job que os pediu (`saida_por_setor`): a média arredondada das contagens publicadas pelas réplicas, ou `null` com o motivo: a regra de k em alguma réplica (`menor_que_k`, `complementar`) ou o corte do diagnóstico no setor (`erro_acima_do_corte`, `erro_nao_medido`, `sem_populacao_sintetica`). Cada réplica publica zero ou pelo menos 5, então a média arredondada ainda pode ficar entre 1 e 4: um zero e um cinco dão 2.",
        "operationId": "get_tract_weeks",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "municipio",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          },
          {
            "name": "semana",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Uma semana; todas, quando ausente"
            },
            "description": "Uma semana; todas, quando ausente"
          },
          {
            "name": "tipo",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "O tipo de evento; por padrão, o primeiro que o job tem"
            },
            "description": "O tipo de evento; por padrão, o primeiro que o job tem"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TractWeeksOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}/cancel": {
      "post": {
        "tags": [
          "Jobs"
        ],
        "summary": "Cancelar um job",
        "operationId": "cancel",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{job_id}/erase": {
      "post": {
        "tags": [
          "Jobs"
        ],
        "summary": "Apagar os dados de um job",
        "description": "Apaga o pedido, as entradas e o resultado de um job encerrado. Nada disso é servido daí em diante, e os objetos guardados somem em minutos; o registro fica, com `registro.apagado_em`, e o job não pode mais ser refeito.",
        "operationId": "erase",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/biblioteca": {
      "get": {
        "tags": [
          "Biblioteca"
        ],
        "summary": "Listar a biblioteca de campanhas",
        "description": "Modelos de campanha por setor para começar, e casos públicos em que o motor foi conferido contra uma série publicada. Qualquer chave pode ler, sem custo.",
        "operationId": "library",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LibraryOut"
                }
              }
            }
          }
        }
      }
    },
    "/v1/biblioteca/{modelo}": {
      "get": {
        "tags": [
          "Biblioteca"
        ],
        "summary": "Ler um modelo de campanha",
        "description": "Um modelo: o plano, as premissas e as perguntas sugeridas. Com um lugar (`uf`, `municipio` ou os dois), também o pedido para ele (`pedido`), conferido como a cotação confere.",
        "operationId": "library_template",
        "parameters": [
          {
            "name": "modelo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "O id do modelo, como a biblioteca o lista"
            },
            "description": "O id do modelo, como a biblioteca o lista"
          },
          {
            "name": "uf",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "description": "Uma UF do lugar, pela sigla de duas letras; por padrão, as UFs dos municípios dados"
            },
            "description": "Uma UF do lugar, pela sigla de duas letras; por padrão, as UFs dos municípios dados"
          },
          {
            "name": "municipio",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "description": "Um município do lugar, pelo código IBGE de 7 dígitos"
            },
            "description": "Um município do lugar, pelo código IBGE de 7 dígitos"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas/pedido-calibracao": {
      "get": {
        "tags": [
          "Calibrações"
        ],
        "summary": "Schema do pedido de calibração",
        "description": "O JSON Schema do pedido de calibração (draft 2020-12), gerado do contrato, com o pedido de campanha de que ele parte em `$defs`. `serie.sha256` não é obrigatório: a plataforma calcula o hash da série a partir das linhas. Público: um programa ou um agente o lê antes de enviar qualquer coisa.",
        "operationId": "calibration_schema",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/v1/calibracoes/estimate": {
      "post": {
        "tags": [
          "Calibrações"
        ],
        "summary": "Cotar uma calibração",
        "description": "Confere o pedido e a série e cota a calibração sem reservar nada (a tarifa da simulação sobre cada rodada que ela faz).",
        "operationId": "estimate_calibration",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalibrationIn"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalibrationQuoteOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/calibracoes": {
      "post": {
        "tags": [
          "Calibrações"
        ],
        "summary": "Enviar uma calibração",
        "description": "Reserva o preço cotado e põe a calibração na fila como um job do tipo `calibracao`; acompanhe com `GET /v1/jobs/{id}`. O resultado traz o cenário calibrado, a busca e o veredito fora da amostra.",
        "operationId": "submit_calibration",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalibrationIn"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/calibracoes/{job_id}": {
      "get": {
        "tags": [
          "Calibrações"
        ],
        "summary": "Ler a resposta de uma calibração",
        "description": "O veredito fora da amostra de uma calibração concluída, o que a análise deixou livre ou fixou, a busca e o valor escolhido de cada parâmetro livre, contra a faixa que o pedido deu.",
        "operationId": "get_calibration",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalibrationAnswerOut"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/perfil": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler o perfil de um município",
        "description": "Como o município é no chão: a área urbanizada em 2022 e o crescimento dela desde 2019 (IBGE), e a cobertura do solo em 2025 e a área urbana desde 1985 (MapBiomas). Contexto para planejamento; não muda uma simulação. `fontes` traz os créditos que as licenças exigem.",
        "operationId": "municipality_profile",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/setores": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler os setores censitários de um município",
        "description": "O município por setor censitário: cobertura do solo (MapBiomas), edificações (Google Open Buildings; retidas onde moram de 1 a 4 domicílios) e declividade (Copernicus DEM), com um resumo dos setores. Contexto, nunca entrada de uma simulação; `fontes` e `aviso` são o que as licenças pedem para mostrar junto com os números.",
        "operationId": "municipality_tracts",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 5000,
              "minimum": 0,
              "description": "Setores na página; 0 para só o resumo",
              "default": 500
            },
            "description": "Setores na página; 0 para só o resumo"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/relevo": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler o relevo de um município",
        "description": "O relevo do município como uma grade de alturas (Copernicus DEM GLO-30): `caixa` (o retângulo em graus), `n` (pontos por lado), `passo_m`, `altitude_min` e `altitude_max`, `piso_zero`, `quadro` e `z`, as alturas em metros como int16 little endian, de norte a sul, em base64. `quadro=urbano` (o padrão) é enquadrado pelos setores urbanos; `quadro=municipio` é uma grade mais grossa (160 pontos por lado) do município inteiro, com uma margem das terras vizinhas. `fonte` traz o crédito e o aviso que a licença pede para mostrar com o relevo. Com gzip. 404 `relief_missing` para um município que os dados não cobrem.",
        "operationId": "municipality_relief",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          },
          {
            "name": "quadro",
            "in": "query",
            "required": false,
            "schema": {
              "enum": [
                "urbano",
                "municipio"
              ],
              "type": "string",
              "description": "`urbano`: a grade fina enquadrada pelos setores urbanos (o padrão); `municipio`: uma grade mais grossa do município inteiro, com uma margem dos vizinhos",
              "default": "urbano"
            },
            "description": "`urbano`: a grade fina enquadrada pelos setores urbanos (o padrão); `municipio`: uma grade mais grossa do município inteiro, com uma margem dos vizinhos"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {}
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/escolas": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler as escolas localizadas de um município",
        "description": "As escolas ativas do município com coordenada (INEP, Catálogo de Escolas e Censo Escolar 2024): o código INEP, a coordenada que a escola declara, as etapas em que tem matrícula e `usada`, se ela é a escola mais próxima de algum setor. `fontes` e `aviso` vêm junto.",
        "operationId": "municipality_schools",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/saude": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler as unidades de saúde localizadas de um município",
        "description": "As unidades de saúde ativas do município com coordenada (Ministério da Saúde, CNES): o código CNES, a coordenada que a unidade declara, o grupo (`atencao_basica`, `pronto_atendimento` ou `hospital`) e o tipo, e `usada`, se ela é a mais próxima de algum setor. Toda unidade ativa conta, pública ou privada. `fontes` e `aviso` vêm junto.",
        "operationId": "municipality_health",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/chuva": {
      "get": {
        "tags": [
          "Cidades"
        ],
        "summary": "Ler a chuva de um município",
        "description": "A chuva mensal do município desde janeiro de 1981 (CHIRPS v3, uma estimativa de satélite calibrada com pluviômetros numa grade de cerca de 5 km, na média da área do município): `normal` (a normal de 1991–2020 de cada mês e do ano, e o mês mais chuvoso), `anos` (o total de cada ano, os meses que ele soma e a anomalia contra a normal; um ano com menos de doze meses fica sem anomalia) e `meses` (a série mensal). É contexto, nunca entrada de uma simulação; `fontes` e `aviso` vêm junto com os números.",
        "operationId": "municipality_rainfall",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/diagnosticos": {
      "get": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Listar as cidades que o projeto abriu",
        "description": "As cidades cujo diagnóstico o projeto da chave abriu, da mais recente para a mais antiga.",
        "operationId": "list_diagnoses",
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            }
          }
        }
      }
    },
    "/v1/diagnosticos/{codigo}/cotacao": {
      "get": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Cotar o diagnóstico de uma cidade",
        "description": "O diagnóstico da cidade para o projeto da chave, na release mais nova: os setores, o preço (zero desde 12/10/2026; uma cidade aberta antes dessa data mostra o preço que o recibo dela registrou) e `aberto`, se o projeto já a abriu ali. Uma cidade que o projeto abriu em qualquer release também traz `release_aberta`, a release em que ela é lida: uma cidade aberta numa release mais antiga fica nela até o projeto abrir a mais nova.",
        "operationId": "quote_diagnosis",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/diagnosticos/{codigo}": {
      "post": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Abrir o diagnóstico de uma cidade",
        "description": "Abre a cidade para o projeto da chave na release mais nova, sem custo: 201 na primeira vez, 200 com o mesmo recibo depois.",
        "operationId": "open_diagnosis",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Ler o diagnóstico de uma cidade",
        "description": "O diagnóstico de uma cidade aberta, por setor censitário. Sem `variavel`, o resumo: as variáveis, os setores e quantos mantêm os números modelados abaixo do corte de erro. Com ela, aquela variável em listas por setor: o que o IBGE observou, ou as contagens da população sintética com o erro do setor (escondidas acima do corte de 0,50, com o motivo). Com `variavel=escolas`, a distância em linha reta de cada setor até a escola mais próxima de cada etapa, em metros, com o código INEP da escola e a parcela das escolas da cidade com coordenada. Os dois são lidos na release que o projeto abriu (`release`) e dizem a release mais nova em que a cidade pode ser aberta (`release_mais_nova`).",
        "operationId": "read_diagnosis",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          },
          {
            "name": "variavel",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Uma variável do diagnóstico; sem ela, o resumo da cidade"
            },
            "description": "Uma variável do diagnóstico; sem ela, o resumo da cidade"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/setores/geometria": {
      "get": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Ler os contornos dos setores de um município",
        "description": "Os setores censitários do município em GeoJSON (malha do IBGE, simplificada para cerca de 11 m, uma feição por setor com a propriedade `setor`), com gzip.",
        "operationId": "tract_outlines",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/municipios/{codigo}/setores/nomes": {
      "get": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Ler os nomes dos setores de um município",
        "description": "Os setores censitários do município pelo nome. Para cada setor: `nome`, o rótulo pelo qual o console o lê, um por setor da cidade: o bairro que o município informou ao IBGE; senão o aglomerado rural ou o núcleo urbano da malha do IBGE; senão o lugar do OpenStreetMap dentro do setor, ou o limite de nível 10 do OpenStreetMap que o contém; senão \"perto de\" o lugar mais próximo da cidade a até 1 km do centro do setor; senão o distrito do IBGE; e por fim os últimos dígitos do código. `lugar` é só o nome desse lugar; `origem` diz de onde o nome vem (`ibge_bairro`, `ibge_aglomerado`, `ibge_nucleo`, `osm_dentro`, `osm_limite`, `osm_perto` ou `ibge_distrito`), com o `credito`; `distancia_m` é a distância para `osm_perto`, em metros. `bairro` (`null` onde o município não informou), `distrito` e `subdistrito` são os do IBGE (malha de setores de 2022). `fontes` lista o crédito de cada fonte: um nome do OpenStreetMap aparece com \"© colaboradores do OpenStreetMap\" (ODbL). Dados públicos: não é preciso abrir a cidade.",
        "operationId": "tract_names",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/diagnosticos/{codigo}/crescimento": {
      "post": {
        "tags": [
          "Diagnóstico"
        ],
        "summary": "Estimar o que um loteamento novo pede da cidade",
        "description": "O que um loteamento novo pede de uma cidade aberta: os moradores e as crianças que ele traz, por analogia com os cinco setores urbanos mais próximos (com a faixa que a medição sustenta), a escola mais próxima de cada etapa com as matrículas, a unidade de saúde mais próxima de cada grupo, o saneamento e a declividade dos setores de referência. Cada resposta tem um número, a base e uma frase; a que os dados não conseguem dar volta retida, com o motivo. As tabelas são as do diagnóstico da cidade na release que o projeto abriu (`release`, com `release_mais_nova`, como o diagnóstico as dá). Não gasta nada; as recusas trazem códigos `growth_*`.",
        "operationId": "estimate_growth",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{7}$",
              "description": "O código IBGE do município"
            },
            "description": "O código IBGE do município"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "description": "O pedido de crescimento como a referência o mostra. Quem decide é o contrato: um pedido fora dele é recusado com um código `growth_*` e o campo culpado.",
                "examples": [
                  {
                    "versao": 1,
                    "municipio": "2601201",
                    "unidades": 200,
                    "poligono": [
                      [
                        -37.06,
                        -8.42
                      ],
                      [
                        -37.05,
                        -8.42
                      ],
                      [
                        -37.05,
                        -8.41
                      ],
                      [
                        -37.06,
                        -8.41
                      ]
                    ]
                  }
                ],
                "title": "Pedido de crescimento",
                "oneOf": [
                  {
                    "required": [
                      "poligono"
                    ]
                  },
                  {
                    "required": [
                      "setores"
                    ]
                  }
                ],
                "properties": {
                  "versao": {
                    "const": 1,
                    "description": "A versão da calculadora",
                    "type": "integer"
                  },
                  "municipio": {
                    "description": "O código IBGE do município, de 7 dígitos, o da rota",
                    "pattern": "^\\d{7}$",
                    "type": "string"
                  },
                  "unidades": {
                    "description": "As unidades habitacionais do loteamento",
                    "maximum": 20000,
                    "minimum": 1,
                    "type": "integer"
                  },
                  "poligono": {
                    "anyOf": [
                      {
                        "items": {
                          "maxItems": 2,
                          "minItems": 2,
                          "prefixItems": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "number"
                            }
                          ],
                          "type": "array"
                        },
                        "maxItems": 1001,
                        "minItems": 3,
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "O contorno como pontos `[longitude, latitude]` no Brasil, no máximo 1.000; a repetição do primeiro ponto no fim é aceita. Exatamente um entre `poligono` e `setores`"
                  },
                  "setores": {
                    "anyOf": [
                      {
                        "items": {
                          "pattern": "^\\d{15}$",
                          "type": "string"
                        },
                        "minItems": 1,
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Os setores censitários (15 dígitos) em que ele fica, em vez de um contorno"
                  }
                },
                "required": [
                  "versao",
                  "municipio",
                  "unidades"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resposta bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnswersOut": {
        "properties": {
          "contrato": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "O contrato de resposta como o job o leu; `null` quando o job não tinha"
          },
          "respostas": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "description": "Uma resposta por pergunta: o número, a base sobre a qual foi lido, o que a regra de k reteve e uma frase; `retido` verdadeiro com `motivo` quando não há número, como numa resposta sobre setores censitários (`base.setores` os lista) em que um deles fica escondido pelo corte de erro do diagnóstico"
          },
          "saida_por_setor": {
            "type": "boolean",
            "description": "Se o job também publicou os eventos por setor censitário e semana"
          },
          "aviso": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "contrato",
          "respostas",
          "saida_por_setor"
        ]
      },
      "CalibrationAnswerOut": {
        "properties": {
          "veredito": {
            "additionalProperties": true,
            "type": "object",
            "description": "O veredito fora da amostra: `resultado` (`aprovada` ou `reprovada`), `tentativa` e cada métrica em `metricas`"
          },
          "identificabilidade": {
            "additionalProperties": true,
            "type": "object",
            "description": "`livres`, os parâmetros que a busca moveu; `fixados`, os mantidos no ponto de partida e por quê; `grupos`, os que a janela só enxerga juntos"
          },
          "busca": {
            "additionalProperties": true,
            "type": "object",
            "description": "`metodo`, `avaliados` e `perda_janela`, o MAPE médio por bloco do candidato escolhido na janela"
          },
          "parametros": {
            "items": {
              "$ref": "#/components/schemas/ParameterOut"
            },
            "type": "array",
            "description": "O valor escolhido de cada parâmetro livre, contra a faixa que o pedido deu"
          }
        },
        "type": "object",
        "required": [
          "veredito",
          "identificabilidade",
          "busca",
          "parametros"
        ]
      },
      "CalibrationIn": {
        "properties": {
          "pedido": {
            "allOf": [
              {
                "if": {
                  "properties": {
                    "cenario": {
                      "properties": {
                        "familia": {
                          "const": "adocao"
                        }
                      },
                      "required": [
                        "familia"
                      ]
                    }
                  },
                  "required": [
                    "cenario"
                  ]
                },
                "then": {
                  "properties": {
                    "parametros": {
                      "propertyNames": {
                        "enum": [
                          "beta0",
                          "logit_lancamento",
                          "dia_lancamento",
                          "beta_expo",
                          "amortecimento_saturacao",
                          "pesos_canais",
                          "gamma_celulas",
                          "deslocamento_porte"
                        ]
                      }
                    }
                  }
                }
              },
              {
                "if": {
                  "properties": {
                    "cenario": {
                      "properties": {
                        "familia": {
                          "const": "recepcao"
                        }
                      },
                      "required": [
                        "familia"
                      ]
                    }
                  },
                  "required": [
                    "cenario"
                  ]
                },
                "then": {
                  "properties": {
                    "parametros": {
                      "propertyNames": {
                        "enum": [
                          "beta0",
                          "beta_expo",
                          "conversao_social",
                          "pesos_canais",
                          "gamma_celulas"
                        ]
                      }
                    }
                  }
                }
              },
              {
                "if": {
                  "properties": {
                    "serie": {
                      "properties": {
                        "declaracao": {
                          "properties": {
                            "granularidade": {
                              "const": "mes"
                            }
                          },
                          "required": [
                            "granularidade"
                          ]
                        }
                      },
                      "required": [
                        "declaracao"
                      ]
                    }
                  },
                  "required": [
                    "serie"
                  ]
                },
                "then": {
                  "properties": {
                    "janela": {
                      "properties": {
                        "inicio": {
                          "maximum": 999912.0,
                          "minimum": 100001.0
                        },
                        "fim": {
                          "maximum": 999912.0,
                          "minimum": 100001.0
                        }
                      }
                    },
                    "holdout": {
                      "properties": {
                        "inicio": {
                          "maximum": 999912.0,
                          "minimum": 100001.0
                        },
                        "fim": {
                          "maximum": 999912.0,
                          "minimum": 100001.0
                        }
                      }
                    }
                  }
                }
              },
              {
                "if": {
                  "properties": {
                    "serie": {
                      "properties": {
                        "declaracao": {
                          "properties": {
                            "granularidade": {
                              "const": "dia"
                            }
                          },
                          "required": [
                            "granularidade"
                          ]
                        }
                      },
                      "required": [
                        "declaracao"
                      ]
                    }
                  },
                  "required": [
                    "serie"
                  ]
                },
                "then": {
                  "properties": {
                    "janela": {
                      "properties": {
                        "inicio": {
                          "maximum": 99991231.0,
                          "minimum": 10000101.0
                        },
                        "fim": {
                          "maximum": 99991231.0,
                          "minimum": 10000101.0
                        }
                      }
                    },
                    "holdout": {
                      "properties": {
                        "inicio": {
                          "maximum": 99991231.0,
                          "minimum": 10000101.0
                        },
                        "fim": {
                          "maximum": 99991231.0,
                          "minimum": 10000101.0
                        }
                      }
                    }
                  }
                }
              },
              {
                "if": {
                  "properties": {
                    "busca": {
                      "properties": {
                        "metodo": {
                          "const": "grade"
                        }
                      },
                      "required": [
                        "metodo"
                      ]
                    }
                  },
                  "required": [
                    "busca"
                  ]
                },
                "then": {
                  "properties": {
                    "parametros": {
                      "properties": {
                        "beta0": {
                          "required": [
                            "passo"
                          ]
                        },
                        "logit_lancamento": {
                          "required": [
                            "passo"
                          ]
                        },
                        "dia_lancamento": {
                          "required": [
                            "passo"
                          ]
                        },
                        "beta_expo": {
                          "required": [
                            "passo"
                          ]
                        },
                        "amortecimento_saturacao": {
                          "required": [
                            "passo"
                          ]
                        },
                        "conversao_social": {
                          "required": [
                            "passo"
                          ]
                        },
                        "pesos_canais": {
                          "required": [
                            "passo"
                          ]
                        },
                        "gamma_celulas": {
                          "required": [
                            "passo"
                          ]
                        },
                        "deslocamento_porte": {
                          "required": [
                            "passo"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            ],
            "properties": {
              "versao_contrato": {
                "const": 3
              },
              "cenario": {
                "allOf": [
                  {
                    "allOf": [
                      {
                        "if": {
                          "properties": {
                            "familia": {
                              "const": "recepcao"
                            }
                          },
                          "required": [
                            "familia"
                          ]
                        },
                        "then": {
                          "properties": {
                            "mensagem": {
                              "type": "object"
                            },
                            "canais": {
                              "minItems": 1
                            },
                            "lancamento": {
                              "type": "null"
                            },
                            "kpis": {
                              "items": {
                                "enum": [
                                  "alcance",
                                  "ignora",
                                  "absorve",
                                  "repassa",
                                  "rejeita"
                                ]
                              }
                            }
                          },
                          "required": [
                            "mensagem",
                            "canais"
                          ]
                        }
                      },
                      {
                        "if": {
                          "properties": {
                            "familia": {
                              "const": "adocao"
                            }
                          },
                          "required": [
                            "familia"
                          ]
                        },
                        "then": {
                          "properties": {
                            "lancamento": {
                              "type": "object"
                            },
                            "mensagem": {
                              "type": "null"
                            },
                            "canais": {
                              "maxItems": 0
                            },
                            "kpis": {
                              "items": {
                                "enum": [
                                  "adotantes"
                                ]
                              }
                            }
                          },
                          "required": [
                            "lancamento"
                          ]
                        }
                      }
                    ],
                    "properties": {
                      "versao_contrato": {
                        "const": 3
                      },
                      "release": {
                        "type": "string",
                        "pattern": "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
                      },
                      "familia": {
                        "enum": [
                          "adocao",
                          "recepcao"
                        ]
                      },
                      "geografia": {
                        "properties": {
                          "ufs": {
                            "items": {
                              "enum": [
                                "AC",
                                "AL",
                                "AM",
                                "AP",
                                "BA",
                                "CE",
                                "DF",
                                "ES",
                                "GO",
                                "MA",
                                "MG",
                                "MS",
                                "MT",
                                "PA",
                                "PB",
                                "PE",
                                "PI",
                                "PR",
                                "RJ",
                                "RN",
                                "RO",
                                "RR",
                                "RS",
                                "SC",
                                "SE",
                                "SP",
                                "TO"
                              ]
                            },
                            "type": "array",
                            "minItems": 1,
                            "uniqueItems": true
                          },
                          "municipios": {
                            "items": {
                              "type": "string",
                              "pattern": "^[0-9]{7}$"
                            },
                            "type": "array",
                            "uniqueItems": true
                          },
                          "aps": {
                            "items": {
                              "type": "string",
                              "pattern": "^[0-9]{10}$"
                            },
                            "type": "array",
                            "uniqueItems": true
                          }
                        },
                        "additionalProperties": false,
                        "type": "object",
                        "required": [
                          "ufs"
                        ]
                      },
                      "publico": {
                        "properties": {
                          "idades": {
                            "items": {
                              "prefixItems": [
                                {
                                  "enum": [
                                    0,
                                    5,
                                    10,
                                    15,
                                    20,
                                    25,
                                    30,
                                    35,
                                    40,
                                    45,
                                    50,
                                    55,
                                    60,
                                    65,
                                    70,
                                    75,
                                    80
                                  ]
                                },
                                {
                                  "enum": [
                                    4,
                                    9,
                                    14,
                                    19,
                                    24,
                                    29,
                                    34,
                                    39,
                                    44,
                                    49,
                                    54,
                                    59,
                                    64,
                                    69,
                                    74,
                                    79,
                                    null
                                  ]
                                }
                              ],
                              "items": false,
                              "type": "array",
                              "minItems": 2
                            },
                            "type": "array"
                          },
                          "sexos": {
                            "items": {
                              "enum": [
                                "masculino",
                                "feminino"
                              ]
                            },
                            "type": "array",
                            "uniqueItems": true
                          },
                          "niveis_instrucao": {
                            "items": {
                              "enum": [
                                "fundamental_incompleto",
                                "fundamental_completo",
                                "medio_completo",
                                "superior_completo"
                              ]
                            },
                            "type": "array",
                            "uniqueItems": true
                          },
                          "faixas_renda": {
                            "items": {
                              "type": "integer",
                              "maximum": 4.0,
                              "minimum": 0.0
                            },
                            "type": "array",
                            "uniqueItems": true
                          },
                          "racas": {
                            "items": {
                              "enum": [
                                "branca",
                                "preta",
                                "amarela",
                                "parda",
                                "indigena"
                              ]
                            },
                            "type": "array",
                            "uniqueItems": true
                          }
                        },
                        "additionalProperties": false,
                        "type": "object"
                      },
                      "canais": {
                        "items": {
                          "properties": {
                            "canal": {
                              "enum": [
                                "digital",
                                "tv",
                                "radio",
                                "exterior"
                              ]
                            },
                            "dia_inicio": {
                              "type": "integer",
                              "maximum": 65535.0,
                              "minimum": 1.0
                            },
                            "dia_fim": {
                              "type": "integer",
                              "maximum": 65535.0,
                              "minimum": 1.0
                            },
                            "intensidade": {
                              "type": "number",
                              "maximum": 1.0,
                              "exclusiveMinimum": 0.0
                            }
                          },
                          "additionalProperties": false,
                          "type": "object",
                          "required": [
                            "canal",
                            "dia_inicio",
                            "dia_fim",
                            "intensidade"
                          ]
                        },
                        "type": "array"
                      },
                      "mensagem": {
                        "anyOf": [
                          {
                            "type": "null"
                          },
                          {
                            "properties": {
                              "stim_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{32}$"
                              },
                              "template_ver": {
                                "type": "string",
                                "pattern": "\\S"
                              },
                              "politica": {
                                "type": "string",
                                "pattern": "\\S"
                              }
                            },
                            "additionalProperties": false,
                            "type": "object",
                            "required": [
                              "stim_id",
                              "template_ver",
                              "politica"
                            ]
                          }
                        ]
                      },
                      "lancamento": {
                        "anyOf": [
                          {
                            "type": "null"
                          },
                          {
                            "if": {
                              "properties": {
                                "cenario_base": {
                                  "const": "calibracao"
                                }
                              },
                              "required": [
                                "cenario_base"
                              ]
                            },
                            "then": {
                              "required": [
                                "calibracao"
                              ]
                            },
                            "else": {
                              "not": {
                                "required": [
                                  "calibracao"
                                ]
                              }
                            },
                            "properties": {
                              "dia": {
                                "type": "integer",
                                "maximum": 65535.0,
                                "minimum": 1.0
                              },
                              "cenario_base": {
                                "enum": [
                                  "pix",
                                  "calibracao"
                                ]
                              },
                              "calibracao": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
                              }
                            },
                            "additionalProperties": false,
                            "type": "object",
                            "required": [
                              "dia",
                              "cenario_base"
                            ]
                          }
                        ]
                      },
                      "horizonte": {
                        "properties": {
                          "data_inicio": {
                            "type": "string",
                            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
                            "format": "date"
                          },
                          "dias": {
                            "type": "integer",
                            "maximum": 65535.0,
                            "minimum": 1.0
                          }
                        },
                        "additionalProperties": false,
                        "type": "object",
                        "required": [
                          "data_inicio",
                          "dias"
                        ]
                      },
                      "replicas": {
                        "type": "integer",
                        "maximum": 20.0,
                        "minimum": 1.0
                      },
                      "grupo_comparacao": {
                        "type": "string",
                        "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
                      },
                      "kpis": {
                        "items": {
                          "enum": [
                            "adotantes",
                            "alcance",
                            "ignora",
                            "absorve",
                            "repassa",
                            "rejeita"
                          ]
                        },
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true
                      },
                      "nome": {
                        "type": "string",
                        "maxLength": 80
                      },
                      "descricao": {
                        "type": "string",
                        "maxLength": 500
                      },
                      "saida_por_setor": {
                        "type": "boolean"
                      },
                      "contrato_de_resposta": {
                        "anyOf": [
                          {
                            "type": "null"
                          },
                          {
                            "properties": {
                              "versao": {
                                "const": 1
                              },
                              "perguntas": {
                                "items": {
                                  "oneOf": [
                                    {
                                      "allOf": [
                                        {
                                          "if": {
                                            "properties": {
                                              "forma": {
                                                "const": "quando"
                                              }
                                            },
                                            "required": [
                                              "forma"
                                            ]
                                          },
                                          "then": {
                                            "properties": {
                                              "momento": {
                                                "required": [
                                                  "parte"
                                                ]
                                              }
                                            }
                                          },
                                          "else": {
                                            "properties": {
                                              "momento": {
                                                "required": [
                                                  "semana"
                                                ]
                                              }
                                            }
                                          }
                                        },
                                        {
                                          "if": {
                                            "properties": {
                                              "forma": {
                                                "const": "onde"
                                              }
                                            },
                                            "required": [
                                              "forma"
                                            ]
                                          },
                                          "then": {},
                                          "else": {
                                            "not": {
                                              "required": [
                                                "ordem"
                                              ]
                                            }
                                          }
                                        }
                                      ],
                                      "properties": {
                                        "id": {
                                          "type": "string",
                                          "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                        },
                                        "forma": {
                                          "enum": [
                                            "quantos",
                                            "quando",
                                            "onde"
                                          ]
                                        },
                                        "medida": {
                                          "enum": [
                                            "adotantes",
                                            "alcance",
                                            "ignora",
                                            "absorve",
                                            "repassa",
                                            "rejeita",
                                            "adocao",
                                            "exposta_social",
                                            "exposta_midia_medida",
                                            "exposta_midia_declarada",
                                            "exposta_midia_ambas",
                                            "ignora",
                                            "absorve",
                                            "repassa",
                                            "rejeita"
                                          ]
                                        },
                                        "publico": {
                                          "properties": {
                                            "grupo_idade": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 6.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            },
                                            "sexo": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 1.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            },
                                            "renda": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 4.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            },
                                            "escolaridade": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 4.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            },
                                            "raca": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 5.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            },
                                            "faixa_etaria_5": {
                                              "items": {
                                                "type": "integer",
                                                "maximum": 16.0,
                                                "minimum": 0.0
                                              },
                                              "type": "array",
                                              "uniqueItems": true
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object"
                                        },
                                        "territorio": {
                                          "oneOf": [
                                            {
                                              "properties": {
                                                "municipios": {
                                                  "items": {
                                                    "type": "string",
                                                    "pattern": "^[0-9]{7}$"
                                                  },
                                                  "type": "array",
                                                  "maxItems": 5000,
                                                  "minItems": 1,
                                                  "uniqueItems": true
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object",
                                              "required": [
                                                "municipios"
                                              ]
                                            },
                                            {
                                              "properties": {
                                                "setores": {
                                                  "items": {
                                                    "type": "string",
                                                    "pattern": "^[0-9]{15}$"
                                                  },
                                                  "type": "array",
                                                  "maxItems": 5000,
                                                  "minItems": 1,
                                                  "uniqueItems": true
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object",
                                              "required": [
                                                "setores"
                                              ]
                                            },
                                            {
                                              "properties": {
                                                "ponto": {
                                                  "prefixItems": [
                                                    {
                                                      "type": "number",
                                                      "maximum": -28.0,
                                                      "minimum": -75.0
                                                    },
                                                    {
                                                      "type": "number",
                                                      "maximum": 6.0,
                                                      "minimum": -34.0
                                                    }
                                                  ],
                                                  "items": false,
                                                  "type": "array",
                                                  "minItems": 2
                                                },
                                                "raio_m": {
                                                  "type": "integer",
                                                  "maximum": 50000.0,
                                                  "minimum": 50.0
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object",
                                              "required": [
                                                "ponto",
                                                "raio_m"
                                              ]
                                            }
                                          ]
                                        },
                                        "momento": {
                                          "oneOf": [
                                            {
                                              "properties": {
                                                "semana": {
                                                  "type": "integer",
                                                  "minimum": 1.0
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object",
                                              "required": [
                                                "semana"
                                              ]
                                            },
                                            {
                                              "properties": {
                                                "parte": {
                                                  "type": "number",
                                                  "maximum": 1.0,
                                                  "exclusiveMinimum": 0.0
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object",
                                              "required": [
                                                "parte"
                                              ]
                                            }
                                          ]
                                        },
                                        "ordem": {
                                          "enum": [
                                            "maior",
                                            "menor"
                                          ]
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "id",
                                        "forma",
                                        "medida",
                                        "territorio",
                                        "momento"
                                      ]
                                    },
                                    {
                                      "properties": {
                                        "id": {
                                          "type": "string",
                                          "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                        },
                                        "forma": {
                                          "const": "comparar"
                                        },
                                        "variantes": {
                                          "items": {
                                            "type": "string",
                                            "minLength": 1
                                          },
                                          "type": "array",
                                          "maxItems": 2,
                                          "minItems": 2,
                                          "uniqueItems": true
                                        },
                                        "pergunta": {
                                          "allOf": [
                                            {
                                              "if": {
                                                "properties": {
                                                  "forma": {
                                                    "const": "quando"
                                                  }
                                                },
                                                "required": [
                                                  "forma"
                                                ]
                                              },
                                              "then": {
                                                "properties": {
                                                  "momento": {
                                                    "required": [
                                                      "parte"
                                                    ]
                                                  }
                                                }
                                              },
                                              "else": {
                                                "properties": {
                                                  "momento": {
                                                    "required": [
                                                      "semana"
                                                    ]
                                                  }
                                                }
                                              }
                                            },
                                            {
                                              "if": {
                                                "properties": {
                                                  "forma": {
                                                    "const": "onde"
                                                  }
                                                },
                                                "required": [
                                                  "forma"
                                                ]
                                              },
                                              "then": {},
                                              "else": {
                                                "not": {
                                                  "required": [
                                                    "ordem"
                                                  ]
                                                }
                                              }
                                            }
                                          ],
                                          "properties": {
                                            "id": {
                                              "type": "string",
                                              "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                            },
                                            "forma": {
                                              "enum": [
                                                "quantos",
                                                "quando",
                                                "onde"
                                              ]
                                            },
                                            "medida": {
                                              "enum": [
                                                "adotantes",
                                                "alcance",
                                                "ignora",
                                                "absorve",
                                                "repassa",
                                                "rejeita",
                                                "adocao",
                                                "exposta_social",
                                                "exposta_midia_medida",
                                                "exposta_midia_declarada",
                                                "exposta_midia_ambas",
                                                "ignora",
                                                "absorve",
                                                "repassa",
                                                "rejeita"
                                              ]
                                            },
                                            "publico": {
                                              "properties": {
                                                "grupo_idade": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 6.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                },
                                                "sexo": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 1.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                },
                                                "renda": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 4.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                },
                                                "escolaridade": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 4.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                },
                                                "raca": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 5.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                },
                                                "faixa_etaria_5": {
                                                  "items": {
                                                    "type": "integer",
                                                    "maximum": 16.0,
                                                    "minimum": 0.0
                                                  },
                                                  "type": "array",
                                                  "uniqueItems": true
                                                }
                                              },
                                              "additionalProperties": false,
                                              "type": "object"
                                            },
                                            "territorio": {
                                              "oneOf": [
                                                {
                                                  "properties": {
                                                    "municipios": {
                                                      "items": {
                                                        "type": "string",
                                                        "pattern": "^[0-9]{7}$"
                                                      },
                                                      "type": "array",
                                                      "maxItems": 5000,
                                                      "minItems": 1,
                                                      "uniqueItems": true
                                                    }
                                                  },
                                                  "additionalProperties": false,
                                                  "type": "object",
                                                  "required": [
                                                    "municipios"
                                                  ]
                                                },
                                                {
                                                  "properties": {
                                                    "setores": {
                                                      "items": {
                                                        "type": "string",
                                                        "pattern": "^[0-9]{15}$"
                                                      },
                                                      "type": "array",
                                                      "maxItems": 5000,
                                                      "minItems": 1,
                                                      "uniqueItems": true
                                                    }
                                                  },
                                                  "additionalProperties": false,
                                                  "type": "object",
                                                  "required": [
                                                    "setores"
                                                  ]
                                                },
                                                {
                                                  "properties": {
                                                    "ponto": {
                                                      "prefixItems": [
                                                        {
                                                          "type": "number",
                                                          "maximum": -28.0,
                                                          "minimum": -75.0
                                                        },
                                                        {
                                                          "type": "number",
                                                          "maximum": 6.0,
                                                          "minimum": -34.0
                                                        }
                                                      ],
                                                      "items": false,
                                                      "type": "array",
                                                      "minItems": 2
                                                    },
                                                    "raio_m": {
                                                      "type": "integer",
                                                      "maximum": 50000.0,
                                                      "minimum": 50.0
                                                    }
                                                  },
                                                  "additionalProperties": false,
                                                  "type": "object",
                                                  "required": [
                                                    "ponto",
                                                    "raio_m"
                                                  ]
                                                }
                                              ]
                                            },
                                            "momento": {
                                              "oneOf": [
                                                {
                                                  "properties": {
                                                    "semana": {
                                                      "type": "integer",
                                                      "minimum": 1.0
                                                    }
                                                  },
                                                  "additionalProperties": false,
                                                  "type": "object",
                                                  "required": [
                                                    "semana"
                                                  ]
                                                },
                                                {
                                                  "properties": {
                                                    "parte": {
                                                      "type": "number",
                                                      "maximum": 1.0,
                                                      "exclusiveMinimum": 0.0
                                                    }
                                                  },
                                                  "additionalProperties": false,
                                                  "type": "object",
                                                  "required": [
                                                    "parte"
                                                  ]
                                                }
                                              ]
                                            },
                                            "ordem": {
                                              "enum": [
                                                "maior",
                                                "menor"
                                              ]
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "id",
                                            "forma",
                                            "medida",
                                            "territorio",
                                            "momento"
                                          ]
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "id",
                                        "forma",
                                        "variantes",
                                        "pergunta"
                                      ]
                                    }
                                  ]
                                },
                                "type": "array",
                                "maxItems": 20,
                                "minItems": 1,
                                "uniqueItems": true
                              }
                            },
                            "additionalProperties": false,
                            "type": "object",
                            "required": [
                              "versao",
                              "perguntas"
                            ]
                          }
                        ]
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "versao_contrato",
                      "release",
                      "familia",
                      "geografia",
                      "horizonte",
                      "replicas",
                      "grupo_comparacao",
                      "kpis"
                    ],
                    "title": "Cenário de campanha",
                    "description": "Um pedido de campanha, na versão 3 do contrato; um pedido na versão 2 ainda é aceito e lido como versão 3. Todo campo está declarado aqui; as regras que um JSON Schema não consegue dizer (entre campos, contra a release, a leitura eleitoral do texto livre) são conferidas pelo servidor, com os mesmos códigos estáveis."
                  },
                  {
                    "properties": {
                      "lancamento": {
                        "properties": {
                          "cenario_base": {
                            "not": {
                              "const": "calibracao"
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "serie": {
                "properties": {
                  "declaracao": {
                    "properties": {
                      "versao_contrato": {
                        "const": 1
                      },
                      "granularidade": {
                        "enum": [
                          "mes",
                          "dia"
                        ]
                      },
                      "medida": {
                        "enum": [
                          "novos",
                          "acumulado"
                        ]
                      },
                      "eixos": {
                        "items": {
                          "enum": [
                            "canal",
                            "grupo_idade",
                            "sexo",
                            "renda",
                            "escolaridade",
                            "raca"
                          ]
                        },
                        "type": "array",
                        "uniqueItems": true
                      },
                      "unidade": {
                        "enum": [
                          "municipio",
                          "area_ponderacao"
                        ]
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "versao_contrato",
                      "granularidade",
                      "medida"
                    ]
                  },
                  "sha256": {
                    "not": {
                      "pattern": "\n"
                    },
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$",
                    "description": "Fica de fora: a plataforma calcula o hash da série a partir das linhas e o escreve aqui"
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "declaracao"
                ]
              },
              "janela": {
                "properties": {
                  "inicio": {
                    "type": "integer"
                  },
                  "fim": {
                    "type": "integer"
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "inicio",
                  "fim"
                ]
              },
              "holdout": {
                "properties": {
                  "inicio": {
                    "type": "integer"
                  },
                  "fim": {
                    "type": "integer"
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "inicio",
                  "fim"
                ]
              },
              "parametros": {
                "if": {
                  "required": [
                    "beta_expo"
                  ]
                },
                "then": {
                  "properties": {
                    "pesos_canais": {
                      "properties": {
                        "canais": {
                          "maxItems": 4
                        }
                      },
                      "required": [
                        "canais"
                      ]
                    }
                  }
                },
                "properties": {
                  "beta0": {
                    "properties": {
                      "min": {
                        "type": "number"
                      },
                      "max": {
                        "type": "number"
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "logit_lancamento": {
                    "properties": {
                      "min": {
                        "type": "number"
                      },
                      "max": {
                        "type": "number"
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "dia_lancamento": {
                    "properties": {
                      "min": {
                        "type": "integer",
                        "maximum": 65535.0,
                        "minimum": 1.0
                      },
                      "max": {
                        "type": "integer",
                        "maximum": 65535.0,
                        "minimum": 1.0
                      },
                      "passo": {
                        "type": "integer",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "beta_expo": {
                    "properties": {
                      "min": {
                        "type": "number"
                      },
                      "max": {
                        "type": "number"
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "amortecimento_saturacao": {
                    "properties": {
                      "min": {
                        "type": "number",
                        "maximum": 1.0,
                        "minimum": 0.0
                      },
                      "max": {
                        "type": "number",
                        "maximum": 1.0,
                        "minimum": 0.0
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "conversao_social": {
                    "properties": {
                      "min": {
                        "type": "number",
                        "minimum": 0.0
                      },
                      "max": {
                        "type": "number",
                        "minimum": 0.0
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "pesos_canais": {
                    "properties": {
                      "min": {
                        "type": "number",
                        "minimum": 0.0
                      },
                      "max": {
                        "type": "number",
                        "minimum": 0.0
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      },
                      "canais": {
                        "items": {
                          "enum": [
                            "domicilio",
                            "turma",
                            "estabelecimento",
                            "vizinhanca",
                            "digital"
                          ]
                        },
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "gamma_celulas": {
                    "properties": {
                      "min": {
                        "type": "number"
                      },
                      "max": {
                        "type": "number"
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      },
                      "agrupamento": {
                        "anyOf": [
                          {
                            "const": "celula"
                          },
                          {
                            "items": {
                              "enum": [
                                "regiao",
                                "faixa",
                                "sexo",
                                "raca",
                                "nivel",
                                "renda"
                              ]
                            },
                            "type": "array",
                            "minItems": 1,
                            "uniqueItems": true
                          }
                        ]
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  },
                  "deslocamento_porte": {
                    "properties": {
                      "min": {
                        "type": "number",
                        "maximum": 5.0,
                        "minimum": -5.0
                      },
                      "max": {
                        "type": "number",
                        "maximum": 5.0,
                        "minimum": -5.0
                      },
                      "passo": {
                        "type": "number",
                        "exclusiveMinimum": 0.0
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "min",
                      "max"
                    ]
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "minProperties": 1
              },
              "holdout_espacial": {
                "if": {
                  "properties": {
                    "metodo": {
                      "const": "cliente"
                    }
                  },
                  "required": [
                    "metodo"
                  ]
                },
                "then": {
                  "required": [
                    "municipios"
                  ]
                },
                "else": {
                  "not": {
                    "required": [
                      "municipios"
                    ]
                  }
                },
                "properties": {
                  "metodo": {
                    "enum": [
                      "plataforma",
                      "cliente",
                      "nenhum"
                    ]
                  },
                  "municipios": {
                    "items": {
                      "not": {
                        "pattern": "\n"
                      },
                      "type": "string",
                      "pattern": "^[0-9]{7}$|^[0-9]{10}$"
                    },
                    "type": "array",
                    "minItems": 1,
                    "uniqueItems": true
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "metodo"
                ]
              },
              "busca": {
                "if": {
                  "properties": {
                    "metodo": {
                      "const": "grade"
                    }
                  },
                  "required": [
                    "metodo"
                  ]
                },
                "then": {
                  "not": {
                    "required": [
                      "candidatos"
                    ]
                  }
                },
                "else": {
                  "required": [
                    "candidatos"
                  ]
                },
                "properties": {
                  "metodo": {
                    "enum": [
                      "grade",
                      "aleatoria",
                      "sequencial"
                    ]
                  },
                  "candidatos": {
                    "type": "integer",
                    "maximum": 10000.0,
                    "minimum": 1.0
                  },
                  "replicas": {
                    "type": "integer",
                    "maximum": 20.0,
                    "minimum": 1.0
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "metodo"
                ]
              }
            },
            "additionalProperties": false,
            "type": "object",
            "required": [
              "versao_contrato",
              "cenario",
              "serie",
              "janela",
              "holdout",
              "parametros",
              "busca"
            ],
            "title": "Pedido de calibração",
            "description": "O pedido de calibração sem `serie.sha256`, que a plataforma calcula a partir das linhas; o JSON Schema dele está em `GET /v1/schemas/pedido-calibracao`"
          },
          "serie": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array",
                "maxItems": 150000
              },
              {
                "type": "null"
              }
            ],
            "description": "A série observada, um objeto por linha: `periodo`, `municipio`, os recortes declarados e `contagem`. Envie este campo ou `serie_sha256`"
          },
          "serie_sha256": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Uma série que esta organização agregou de uma das bases dos seus projetos, pelo hash. Envie este campo ou `serie`"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "pedido"
        ]
      },
      "CalibrationQuoteOut": {
        "properties": {
          "release": {
            "type": "string"
          },
          "ufs": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dias": {
            "type": "integer",
            "description": "Dias simulados, até o último dia do teste fora da amostra"
          },
          "rodadas": {
            "type": "integer",
            "description": "As rodadas que o preço cobre: os candidatos da busca, duas por parâmetro livre para a análise do que a série consegue distinguir, e a escolhida"
          },
          "replicas": {
            "type": "integer"
          },
          "pessoa_dias": {
            "type": "integer"
          },
          "preco_micros": {
            "type": "integer",
            "description": "O preço em milionésimos de real"
          },
          "minutos_estimados": {
            "type": "integer",
            "description": "Quanto tempo, mais ou menos, a calibração roda depois de começar, em minutos"
          }
        },
        "type": "object",
        "required": [
          "release",
          "ufs",
          "dias",
          "rodadas",
          "replicas",
          "pessoa_dias",
          "preco_micros",
          "minutos_estimados"
        ]
      },
      "CaseOut": {
        "properties": {
          "id": {
            "type": "string"
          },
          "nome": {
            "type": "string"
          },
          "o_que_foi_medido": {
            "type": "string"
          },
          "release": {
            "type": "string",
            "description": "A release a que a medição se aplica"
          },
          "vale_ate_dia": {
            "type": "integer",
            "description": "O último dia simulado que a medição cobre"
          },
          "resumo": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "description": "Quantas UFs têm cada veredito"
          },
          "ufs": {
            "items": {
              "$ref": "#/components/schemas/CaseStateOut"
            },
            "type": "array",
            "description": "Cada UF, com o seu veredito e o seu erro"
          },
          "testes": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "description": "O que cada teste mede e o seu limite"
          },
          "fonte": {
            "$ref": "#/components/schemas/CaseSourceOut",
            "description": "A série publicada, com o crédito e a licença dela"
          },
          "metodo": {
            "type": "string",
            "description": "A página com o método e todos os números"
          },
          "aviso": {
            "type": "string"
          }
        },
        "type": "object",
        "required": [
          "id",
          "nome",
          "o_que_foi_medido",
          "release",
          "vale_ate_dia",
          "resumo",
          "ufs",
          "testes",
          "fonte",
          "metodo",
          "aviso"
        ]
      },
      "CaseSourceOut": {
        "properties": {
          "credito": {
            "type": "string"
          },
          "licenca": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object",
        "required": [
          "credito",
          "licenca",
          "url"
        ]
      },
      "CaseStateOut": {
        "properties": {
          "uf": {
            "type": "string"
          },
          "veredito": {
            "type": "string",
            "description": "`passou`, `reprovado_declarado` ou `nao_pontuado`"
          },
          "mape_pior": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "O trimestre com o maior erro do total da UF: `trimestre`, `valor` e `limite`, como frações"
          },
          "reprovacoes": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "description": "Cada teste reprovado: `teste`, `periodo`, `valor` e `limite`"
          }
        },
        "type": "object",
        "required": [
          "uf",
          "veredito"
        ]
      },
      "ComparisonOut": {
        "properties": {
          "a": {
            "$ref": "#/components/schemas/ScenarioSummaryOut"
          },
          "b": {
            "$ref": "#/components/schemas/ScenarioSummaryOut"
          },
          "mesmo_grupo_comparacao": {
            "type": "boolean",
            "description": "Se os dois cenários têm o mesmo grupo de comparação e, portanto, os mesmos números aleatórios: aí a diferença vem dos planos, não do acaso"
          },
          "municipios": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "description": "O nome de cada município que as linhas trazem, pelo código IBGE"
          },
          "tabelas": {
            "additionalProperties": {
              "$ref": "#/components/schemas/TableComparisonOut"
            },
            "type": "object",
            "description": "`saturacao`, `alcance_efetivo`, `alcance_potencial`, `contribuicao` e `elasticidade`; uma tabela que nenhum dos dois jobs tem volta vazia"
          }
        },
        "type": "object",
        "required": [
          "a",
          "b",
          "mesmo_grupo_comparacao",
          "tabelas"
        ]
      },
      "FindingsOut": {
        "properties": {
          "tabela": {
            "type": "string"
          },
          "colunas": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "descricao": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "description": "O que cada coluna significa, pelo nome base (`total_media` é `total`)"
          },
          "municipios": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "description": "O nome de cada município que as linhas trazem, pelo código IBGE"
          },
          "linhas": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array"
          },
          "total": {
            "type": "integer"
          },
          "truncado": {
            "type": "boolean"
          },
          "grade": {
            "type": "string",
            "description": "A grade de publicação que as linhas descrevem: `principal`, ou `etaria` (município × faixa etária de 5 anos × sexo) para um público recortado em faixas de 5 anos",
            "default": "principal"
          }
        },
        "type": "object",
        "required": [
          "tabela",
          "colunas",
          "linhas",
          "total",
          "truncado"
        ]
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "HorizonOut": {
        "properties": {
          "data_inicio": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "dias": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object"
      },
      "JobOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "estado": {
            "type": "string"
          },
          "tipo": {
            "type": "string"
          },
          "preco_micros": {
            "type": "integer"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "registro": {
            "additionalProperties": true,
            "type": "object"
          },
          "apagamento_pedido_em": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "project_id",
          "estado",
          "tipo",
          "preco_micros",
          "criado_em",
          "registro"
        ]
      },
      "LibraryOut": {
        "properties": {
          "modelos": {
            "items": {
              "$ref": "#/components/schemas/TemplateSummaryOut"
            },
            "type": "array",
            "description": "Modelos para começar uma campanha"
          },
          "casos": {
            "items": {
              "$ref": "#/components/schemas/CaseOut"
            },
            "type": "array",
            "description": "Casos públicos: onde o motor foi conferido contra uma série publicada, com o erro, a fonte e a licença dela"
          },
          "aviso": {
            "type": "string",
            "description": "O que cada modelo diz de si"
          }
        },
        "type": "object",
        "required": [
          "modelos",
          "casos",
          "aviso"
        ]
      },
      "ParameterOut": {
        "properties": {
          "parametro": {
            "type": "string",
            "description": "Como a análise o nomeia: `beta0`, o peso de um canal, como `pesos_canais[digital]`, ou o deslocamento de nível de um estrato de porte, como `deslocamento_porte[grandes]`"
          },
          "valor": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "O valor escolhido; `null` para um grupo de deslocamentos de célula, que não tem um valor único"
          },
          "min": {
            "type": "number"
          },
          "max": {
            "type": "number"
          },
          "passo": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "na_borda": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`min` ou `max` quando o valor escolhido fica nessa borda da faixa: o melhor ponto que a busca alcançou estava no limite, e uma faixa mais larga pode ter um melhor"
          }
        },
        "type": "object",
        "required": [
          "parametro",
          "valor",
          "min",
          "max",
          "passo",
          "na_borda"
        ]
      },
      "QuoteOut": {
        "properties": {
          "release": {
            "type": "string"
          },
          "ufs": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dias": {
            "type": "integer"
          },
          "variantes": {
            "type": "integer"
          },
          "replicas": {
            "type": "integer"
          },
          "pessoa_dias": {
            "type": "integer"
          },
          "preco_micros": {
            "type": "integer"
          },
          "minutos_estimados": {
            "type": "integer",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "release",
          "ufs",
          "dias",
          "variantes",
          "replicas",
          "pessoa_dias",
          "preco_micros"
        ]
      },
      "Request": {
        "properties": {
          "pedido": {
            "allOf": [
              {
                "if": {
                  "properties": {
                    "familia": {
                      "const": "recepcao"
                    }
                  },
                  "required": [
                    "familia"
                  ]
                },
                "then": {
                  "properties": {
                    "mensagem": {
                      "type": "object"
                    },
                    "canais": {
                      "minItems": 1
                    },
                    "lancamento": {
                      "type": "null"
                    },
                    "kpis": {
                      "items": {
                        "enum": [
                          "alcance",
                          "ignora",
                          "absorve",
                          "repassa",
                          "rejeita"
                        ]
                      }
                    }
                  },
                  "required": [
                    "mensagem",
                    "canais"
                  ]
                }
              },
              {
                "if": {
                  "properties": {
                    "familia": {
                      "const": "adocao"
                    }
                  },
                  "required": [
                    "familia"
                  ]
                },
                "then": {
                  "properties": {
                    "lancamento": {
                      "type": "object"
                    },
                    "mensagem": {
                      "type": "null"
                    },
                    "canais": {
                      "maxItems": 0
                    },
                    "kpis": {
                      "items": {
                        "enum": [
                          "adotantes"
                        ]
                      }
                    }
                  },
                  "required": [
                    "lancamento"
                  ]
                }
              }
            ],
            "properties": {
              "versao_contrato": {
                "const": 3
              },
              "release": {
                "type": "string",
                "pattern": "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
              },
              "familia": {
                "enum": [
                  "adocao",
                  "recepcao"
                ]
              },
              "geografia": {
                "properties": {
                  "ufs": {
                    "items": {
                      "enum": [
                        "AC",
                        "AL",
                        "AM",
                        "AP",
                        "BA",
                        "CE",
                        "DF",
                        "ES",
                        "GO",
                        "MA",
                        "MG",
                        "MS",
                        "MT",
                        "PA",
                        "PB",
                        "PE",
                        "PI",
                        "PR",
                        "RJ",
                        "RN",
                        "RO",
                        "RR",
                        "RS",
                        "SC",
                        "SE",
                        "SP",
                        "TO"
                      ]
                    },
                    "type": "array",
                    "minItems": 1,
                    "uniqueItems": true
                  },
                  "municipios": {
                    "items": {
                      "type": "string",
                      "pattern": "^[0-9]{7}$"
                    },
                    "type": "array",
                    "uniqueItems": true
                  },
                  "aps": {
                    "items": {
                      "type": "string",
                      "pattern": "^[0-9]{10}$"
                    },
                    "type": "array",
                    "uniqueItems": true
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "ufs"
                ]
              },
              "publico": {
                "properties": {
                  "idades": {
                    "items": {
                      "prefixItems": [
                        {
                          "enum": [
                            0,
                            5,
                            10,
                            15,
                            20,
                            25,
                            30,
                            35,
                            40,
                            45,
                            50,
                            55,
                            60,
                            65,
                            70,
                            75,
                            80
                          ]
                        },
                        {
                          "enum": [
                            4,
                            9,
                            14,
                            19,
                            24,
                            29,
                            34,
                            39,
                            44,
                            49,
                            54,
                            59,
                            64,
                            69,
                            74,
                            79,
                            null
                          ]
                        }
                      ],
                      "items": false,
                      "type": "array",
                      "minItems": 2
                    },
                    "type": "array"
                  },
                  "sexos": {
                    "items": {
                      "enum": [
                        "masculino",
                        "feminino"
                      ]
                    },
                    "type": "array",
                    "uniqueItems": true
                  },
                  "niveis_instrucao": {
                    "items": {
                      "enum": [
                        "fundamental_incompleto",
                        "fundamental_completo",
                        "medio_completo",
                        "superior_completo"
                      ]
                    },
                    "type": "array",
                    "uniqueItems": true
                  },
                  "faixas_renda": {
                    "items": {
                      "type": "integer",
                      "maximum": 4.0,
                      "minimum": 0.0
                    },
                    "type": "array",
                    "uniqueItems": true
                  },
                  "racas": {
                    "items": {
                      "enum": [
                        "branca",
                        "preta",
                        "amarela",
                        "parda",
                        "indigena"
                      ]
                    },
                    "type": "array",
                    "uniqueItems": true
                  }
                },
                "additionalProperties": false,
                "type": "object"
              },
              "canais": {
                "items": {
                  "properties": {
                    "canal": {
                      "enum": [
                        "digital",
                        "tv",
                        "radio",
                        "exterior"
                      ]
                    },
                    "dia_inicio": {
                      "type": "integer",
                      "maximum": 65535.0,
                      "minimum": 1.0
                    },
                    "dia_fim": {
                      "type": "integer",
                      "maximum": 65535.0,
                      "minimum": 1.0
                    },
                    "intensidade": {
                      "type": "number",
                      "maximum": 1.0,
                      "exclusiveMinimum": 0.0
                    }
                  },
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "canal",
                    "dia_inicio",
                    "dia_fim",
                    "intensidade"
                  ]
                },
                "type": "array"
              },
              "mensagem": {
                "anyOf": [
                  {
                    "type": "null"
                  },
                  {
                    "properties": {
                      "stim_id": {
                        "type": "string",
                        "pattern": "^[0-9a-f]{32}$"
                      },
                      "template_ver": {
                        "type": "string",
                        "pattern": "\\S"
                      },
                      "politica": {
                        "type": "string",
                        "pattern": "\\S"
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "stim_id",
                      "template_ver",
                      "politica"
                    ]
                  }
                ]
              },
              "lancamento": {
                "anyOf": [
                  {
                    "type": "null"
                  },
                  {
                    "if": {
                      "properties": {
                        "cenario_base": {
                          "const": "calibracao"
                        }
                      },
                      "required": [
                        "cenario_base"
                      ]
                    },
                    "then": {
                      "required": [
                        "calibracao"
                      ]
                    },
                    "else": {
                      "not": {
                        "required": [
                          "calibracao"
                        ]
                      }
                    },
                    "properties": {
                      "dia": {
                        "type": "integer",
                        "maximum": 65535.0,
                        "minimum": 1.0
                      },
                      "cenario_base": {
                        "enum": [
                          "pix",
                          "calibracao"
                        ]
                      },
                      "calibracao": {
                        "type": "string",
                        "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "dia",
                      "cenario_base"
                    ]
                  }
                ]
              },
              "horizonte": {
                "properties": {
                  "data_inicio": {
                    "type": "string",
                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
                    "format": "date"
                  },
                  "dias": {
                    "type": "integer",
                    "maximum": 65535.0,
                    "minimum": 1.0
                  }
                },
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "data_inicio",
                  "dias"
                ]
              },
              "replicas": {
                "type": "integer",
                "maximum": 20.0,
                "minimum": 1.0
              },
              "grupo_comparacao": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
              },
              "kpis": {
                "items": {
                  "enum": [
                    "adotantes",
                    "alcance",
                    "ignora",
                    "absorve",
                    "repassa",
                    "rejeita"
                  ]
                },
                "type": "array",
                "minItems": 1,
                "uniqueItems": true
              },
              "nome": {
                "type": "string",
                "maxLength": 80
              },
              "descricao": {
                "type": "string",
                "maxLength": 500
              },
              "saida_por_setor": {
                "type": "boolean"
              },
              "contrato_de_resposta": {
                "anyOf": [
                  {
                    "type": "null"
                  },
                  {
                    "properties": {
                      "versao": {
                        "const": 1
                      },
                      "perguntas": {
                        "items": {
                          "oneOf": [
                            {
                              "allOf": [
                                {
                                  "if": {
                                    "properties": {
                                      "forma": {
                                        "const": "quando"
                                      }
                                    },
                                    "required": [
                                      "forma"
                                    ]
                                  },
                                  "then": {
                                    "properties": {
                                      "momento": {
                                        "required": [
                                          "parte"
                                        ]
                                      }
                                    }
                                  },
                                  "else": {
                                    "properties": {
                                      "momento": {
                                        "required": [
                                          "semana"
                                        ]
                                      }
                                    }
                                  }
                                },
                                {
                                  "if": {
                                    "properties": {
                                      "forma": {
                                        "const": "onde"
                                      }
                                    },
                                    "required": [
                                      "forma"
                                    ]
                                  },
                                  "then": {},
                                  "else": {
                                    "not": {
                                      "required": [
                                        "ordem"
                                      ]
                                    }
                                  }
                                }
                              ],
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                },
                                "forma": {
                                  "enum": [
                                    "quantos",
                                    "quando",
                                    "onde"
                                  ]
                                },
                                "medida": {
                                  "enum": [
                                    "adotantes",
                                    "alcance",
                                    "ignora",
                                    "absorve",
                                    "repassa",
                                    "rejeita",
                                    "adocao",
                                    "exposta_social",
                                    "exposta_midia_medida",
                                    "exposta_midia_declarada",
                                    "exposta_midia_ambas",
                                    "ignora",
                                    "absorve",
                                    "repassa",
                                    "rejeita"
                                  ]
                                },
                                "publico": {
                                  "properties": {
                                    "grupo_idade": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 6.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    },
                                    "sexo": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 1.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    },
                                    "renda": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 4.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    },
                                    "escolaridade": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 4.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    },
                                    "raca": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 5.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    },
                                    "faixa_etaria_5": {
                                      "items": {
                                        "type": "integer",
                                        "maximum": 16.0,
                                        "minimum": 0.0
                                      },
                                      "type": "array",
                                      "uniqueItems": true
                                    }
                                  },
                                  "additionalProperties": false,
                                  "type": "object"
                                },
                                "territorio": {
                                  "oneOf": [
                                    {
                                      "properties": {
                                        "municipios": {
                                          "items": {
                                            "type": "string",
                                            "pattern": "^[0-9]{7}$"
                                          },
                                          "type": "array",
                                          "maxItems": 5000,
                                          "minItems": 1,
                                          "uniqueItems": true
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "municipios"
                                      ]
                                    },
                                    {
                                      "properties": {
                                        "setores": {
                                          "items": {
                                            "type": "string",
                                            "pattern": "^[0-9]{15}$"
                                          },
                                          "type": "array",
                                          "maxItems": 5000,
                                          "minItems": 1,
                                          "uniqueItems": true
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "setores"
                                      ]
                                    },
                                    {
                                      "properties": {
                                        "ponto": {
                                          "prefixItems": [
                                            {
                                              "type": "number",
                                              "maximum": -28.0,
                                              "minimum": -75.0
                                            },
                                            {
                                              "type": "number",
                                              "maximum": 6.0,
                                              "minimum": -34.0
                                            }
                                          ],
                                          "items": false,
                                          "type": "array",
                                          "minItems": 2
                                        },
                                        "raio_m": {
                                          "type": "integer",
                                          "maximum": 50000.0,
                                          "minimum": 50.0
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "ponto",
                                        "raio_m"
                                      ]
                                    }
                                  ]
                                },
                                "momento": {
                                  "oneOf": [
                                    {
                                      "properties": {
                                        "semana": {
                                          "type": "integer",
                                          "minimum": 1.0
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "semana"
                                      ]
                                    },
                                    {
                                      "properties": {
                                        "parte": {
                                          "type": "number",
                                          "maximum": 1.0,
                                          "exclusiveMinimum": 0.0
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object",
                                      "required": [
                                        "parte"
                                      ]
                                    }
                                  ]
                                },
                                "ordem": {
                                  "enum": [
                                    "maior",
                                    "menor"
                                  ]
                                }
                              },
                              "additionalProperties": false,
                              "type": "object",
                              "required": [
                                "id",
                                "forma",
                                "medida",
                                "territorio",
                                "momento"
                              ]
                            },
                            {
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                },
                                "forma": {
                                  "const": "comparar"
                                },
                                "variantes": {
                                  "items": {
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  "type": "array",
                                  "maxItems": 2,
                                  "minItems": 2,
                                  "uniqueItems": true
                                },
                                "pergunta": {
                                  "allOf": [
                                    {
                                      "if": {
                                        "properties": {
                                          "forma": {
                                            "const": "quando"
                                          }
                                        },
                                        "required": [
                                          "forma"
                                        ]
                                      },
                                      "then": {
                                        "properties": {
                                          "momento": {
                                            "required": [
                                              "parte"
                                            ]
                                          }
                                        }
                                      },
                                      "else": {
                                        "properties": {
                                          "momento": {
                                            "required": [
                                              "semana"
                                            ]
                                          }
                                        }
                                      }
                                    },
                                    {
                                      "if": {
                                        "properties": {
                                          "forma": {
                                            "const": "onde"
                                          }
                                        },
                                        "required": [
                                          "forma"
                                        ]
                                      },
                                      "then": {},
                                      "else": {
                                        "not": {
                                          "required": [
                                            "ordem"
                                          ]
                                        }
                                      }
                                    }
                                  ],
                                  "properties": {
                                    "id": {
                                      "type": "string",
                                      "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
                                    },
                                    "forma": {
                                      "enum": [
                                        "quantos",
                                        "quando",
                                        "onde"
                                      ]
                                    },
                                    "medida": {
                                      "enum": [
                                        "adotantes",
                                        "alcance",
                                        "ignora",
                                        "absorve",
                                        "repassa",
                                        "rejeita",
                                        "adocao",
                                        "exposta_social",
                                        "exposta_midia_medida",
                                        "exposta_midia_declarada",
                                        "exposta_midia_ambas",
                                        "ignora",
                                        "absorve",
                                        "repassa",
                                        "rejeita"
                                      ]
                                    },
                                    "publico": {
                                      "properties": {
                                        "grupo_idade": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 6.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        },
                                        "sexo": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 1.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        },
                                        "renda": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 4.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        },
                                        "escolaridade": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 4.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        },
                                        "raca": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 5.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        },
                                        "faixa_etaria_5": {
                                          "items": {
                                            "type": "integer",
                                            "maximum": 16.0,
                                            "minimum": 0.0
                                          },
                                          "type": "array",
                                          "uniqueItems": true
                                        }
                                      },
                                      "additionalProperties": false,
                                      "type": "object"
                                    },
                                    "territorio": {
                                      "oneOf": [
                                        {
                                          "properties": {
                                            "municipios": {
                                              "items": {
                                                "type": "string",
                                                "pattern": "^[0-9]{7}$"
                                              },
                                              "type": "array",
                                              "maxItems": 5000,
                                              "minItems": 1,
                                              "uniqueItems": true
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "municipios"
                                          ]
                                        },
                                        {
                                          "properties": {
                                            "setores": {
                                              "items": {
                                                "type": "string",
                                                "pattern": "^[0-9]{15}$"
                                              },
                                              "type": "array",
                                              "maxItems": 5000,
                                              "minItems": 1,
                                              "uniqueItems": true
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "setores"
                                          ]
                                        },
                                        {
                                          "properties": {
                                            "ponto": {
                                              "prefixItems": [
                                                {
                                                  "type": "number",
                                                  "maximum": -28.0,
                                                  "minimum": -75.0
                                                },
                                                {
                                                  "type": "number",
                                                  "maximum": 6.0,
                                                  "minimum": -34.0
                                                }
                                              ],
                                              "items": false,
                                              "type": "array",
                                              "minItems": 2
                                            },
                                            "raio_m": {
                                              "type": "integer",
                                              "maximum": 50000.0,
                                              "minimum": 50.0
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "ponto",
                                            "raio_m"
                                          ]
                                        }
                                      ]
                                    },
                                    "momento": {
                                      "oneOf": [
                                        {
                                          "properties": {
                                            "semana": {
                                              "type": "integer",
                                              "minimum": 1.0
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "semana"
                                          ]
                                        },
                                        {
                                          "properties": {
                                            "parte": {
                                              "type": "number",
                                              "maximum": 1.0,
                                              "exclusiveMinimum": 0.0
                                            }
                                          },
                                          "additionalProperties": false,
                                          "type": "object",
                                          "required": [
                                            "parte"
                                          ]
                                        }
                                      ]
                                    },
                                    "ordem": {
                                      "enum": [
                                        "maior",
                                        "menor"
                                      ]
                                    }
                                  },
                                  "additionalProperties": false,
                                  "type": "object",
                                  "required": [
                                    "id",
                                    "forma",
                                    "medida",
                                    "territorio",
                                    "momento"
                                  ]
                                }
                              },
                              "additionalProperties": false,
                              "type": "object",
                              "required": [
                                "id",
                                "forma",
                                "variantes",
                                "pergunta"
                              ]
                            }
                          ]
                        },
                        "type": "array",
                        "maxItems": 20,
                        "minItems": 1,
                        "uniqueItems": true
                      }
                    },
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "versao",
                      "perguntas"
                    ]
                  }
                ]
              }
            },
            "additionalProperties": false,
            "type": "object",
            "required": [
              "versao_contrato",
              "release",
              "familia",
              "geografia",
              "horizonte",
              "replicas",
              "grupo_comparacao",
              "kpis"
            ],
            "title": "Cenário de campanha",
            "description": "Um pedido de campanha, na versão 3 do contrato; um pedido na versão 2 ainda é aceito e lido como versão 3. Todo campo está declarado aqui; as regras que um JSON Schema não consegue dizer (entre campos, contra a release, a leitura eleitoral do texto livre) são conferidas pelo servidor, com os mesmos códigos estáveis."
          }
        },
        "type": "object",
        "required": [
          "pedido"
        ],
        "examples": [
          {
            "pedido": {
              "canais": [
                {
                  "canal": "digital",
                  "dia_fim": 14,
                  "dia_inicio": 1,
                  "intensidade": 0.5
                },
                {
                  "canal": "radio",
                  "dia_fim": 21,
                  "dia_inicio": 7,
                  "intensidade": 0.3
                }
              ],
              "familia": "recepcao",
              "geografia": {
                "municipios": [
                  "3106200"
                ],
                "ufs": [
                  "MG"
                ]
              },
              "grupo_comparacao": "campanha-bh",
              "horizonte": {
                "data_inicio": "2026-11-01",
                "dias": 30
              },
              "kpis": [
                "alcance",
                "repassa"
              ],
              "mensagem": {
                "politica": "pol-ref",
                "stim_id": "af9cca9c97fcb5b610476bde8756e849",
                "template_ver": "tpl-ref"
              },
              "nome": "Campanha em Belo Horizonte",
              "publico": {
                "faixas_renda": [
                  1,
                  2,
                  3
                ],
                "idades": [
                  [
                    20,
                    59
                  ]
                ]
              },
              "release": "v2.0.0",
              "replicas": 2,
              "versao_contrato": 3
            }
          }
        ]
      },
      "ScenarioSummaryOut": {
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "release": {
            "type": "string"
          },
          "familia": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "horizonte": {
            "$ref": "#/components/schemas/HorizonOut"
          },
          "grupo_comparacao": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "grade": {
            "type": "string",
            "description": "A grade que os achados descrevem: `principal` ou `etaria`"
          },
          "veredito": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "O veredito fora da amostra de cada UF quando o cenário rodou numa base calibrada, como a tabela `veredito` dos achados o dá; `null` caso contrário"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "nome",
          "release",
          "familia",
          "horizonte",
          "grupo_comparacao",
          "grade",
          "veredito"
        ]
      },
      "TableComparisonOut": {
        "properties": {
          "chaves": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "description": "As colunas que pareiam as linhas dos dois jobs"
          },
          "valores": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "description": "Os números principais: as médias entre as réplicas, ou as contagens de uma tabela sem médias"
          },
          "linhas": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "description": "Uma linha por chave: as colunas dela, `a` e `b` (`null` onde aquele job não tem essa linha) e `diferenca`, b menos a"
          },
          "total": {
            "type": "integer",
            "description": "Quantas linhas pular antes da página"
          },
          "truncado": {
            "type": "boolean"
          }
        },
        "type": "object",
        "required": [
          "chaves",
          "valores",
          "linhas",
          "total",
          "truncado"
        ]
      },
      "TemplateOut": {
        "properties": {
          "id": {
            "type": "string",
            "description": "O id do modelo, para `GET /v1/biblioteca/{modelo}`"
          },
          "setor": {
            "type": "string",
            "description": "O setor para o qual o modelo foi escrito"
          },
          "nome": {
            "type": "string"
          },
          "para_que_serve": {
            "type": "string",
            "description": "O que o modelo ajuda a decidir"
          },
          "premissas": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "description": "As premissas do modelo em palavras simples: o público, os canais com os dias e a intensidade, o horizonte. Um modelo traz premissas, não resultados"
          },
          "calibracao": {
            "type": "string",
            "description": "`nao_calibrado`: a recepção da mensagem ainda não foi calibrada contra dados reais, e um job feito do modelo diz isso"
          },
          "cenario": {
            "additionalProperties": true,
            "type": "object",
            "description": "Um pedido de campanha sem o lugar e sem o que a plataforma preenche: `geografia`, `release`, `mensagem`, `grupo_comparacao`, `nome` e `horizonte.data_inicio`"
          },
          "perguntas": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "description": "Perguntas sugeridas do contrato de resposta, cada uma com `texto`, a redação dela; o território e o público vêm com o lugar"
          },
          "aviso": {
            "type": "string",
            "description": "O que cada modelo diz de si"
          },
          "pedido": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Com `uf` ou `municipio`, o modelo para aquele lugar: um pedido de campanha completo, pronto para `POST /v1/jobs/estimate`, na release mais nova, começando no primeiro dia do mês que vem, com as perguntas sugeridas sobre os municípios escolhidos (nenhuma para uma UF inteira). Mude qualquer campo antes de enviar"
          }
        },
        "type": "object",
        "required": [
          "id",
          "setor",
          "nome",
          "para_que_serve",
          "premissas",
          "calibracao",
          "cenario",
          "perguntas",
          "aviso"
        ]
      },
      "TemplateSummaryOut": {
        "properties": {
          "id": {
            "type": "string",
            "description": "O id do modelo, para `GET /v1/biblioteca/{modelo}`"
          },
          "setor": {
            "type": "string",
            "description": "O setor para o qual o modelo foi escrito"
          },
          "nome": {
            "type": "string"
          },
          "para_que_serve": {
            "type": "string",
            "description": "O que o modelo ajuda a decidir"
          },
          "premissas": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "description": "As premissas do modelo em palavras simples: o público, os canais com os dias e a intensidade, o horizonte. Um modelo traz premissas, não resultados"
          },
          "calibracao": {
            "type": "string",
            "description": "`nao_calibrado`: a recepção da mensagem ainda não foi calibrada contra dados reais, e um job feito do modelo diz isso"
          }
        },
        "type": "object",
        "required": [
          "id",
          "setor",
          "nome",
          "para_que_serve",
          "premissas",
          "calibracao"
        ]
      },
      "TractWeeksOut": {
        "properties": {
          "municipio": {
            "type": "string"
          },
          "semanas": {
            "type": "integer",
            "description": "As semanas que o job publicou (blocos de 7 dias a partir do dia 1)"
          },
          "tipos": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "description": "Os tipos de evento que a tabela tem para o job"
          },
          "tipo": {
            "type": "string"
          },
          "semana": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "corte_erro": {
            "type": "number",
            "description": "O corte de erro do diagnóstico aplicado a cada setor"
          },
          "linhas": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "description": "Uma linha por setor e semana: `n`, a média arredondada das contagens publicadas pelas réplicas (cada uma zero ou pelo menos 5), ou `null` com `motivo` (`menor_que_k`, `complementar`, `erro_acima_do_corte`, `erro_nao_medido` ou `sem_populacao_sintetica`)"
          },
          "motivos": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "description": "Quantos pares de setor e semana cada motivo escondeu"
          },
          "total": {
            "type": "integer"
          },
          "truncado": {
            "type": "boolean"
          }
        },
        "type": "object",
        "required": [
          "municipio",
          "semanas",
          "tipos",
          "tipo",
          "semana",
          "corte_erro",
          "linhas",
          "motivos",
          "total",
          "truncado"
        ]
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Local"
          },
          "msg": {
            "type": "string",
            "title": "Mensagem"
          },
          "type": {
            "type": "string",
            "title": "Tipo do erro"
          },
          "input": {},
          "ctx": {
            "type": "object",
            "title": "Contexto"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ]
      },
      "WhoAmI": {
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "key_prefix": {
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object",
        "required": [
          "project_id",
          "organization_id",
          "key_prefix",
          "scopes"
        ]
      }
    },
    "securitySchemes": {
      "projectKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Uma chave de API de projeto, `bs_<prefixo>_<segredo>`, criada na página do projeto."
      }
    }
  }
}
