From 3506a69f15fdf1c1c80acec26e906e6f25eeff14 Mon Sep 17 00:00:00 2001 From: Murilo Ijanc Date: Mon, 27 Jul 2026 20:38:46 -0300 Subject: Name the municipality behind a CEP that does not exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A CEP that fails is rarely a random number. It is usually someone who knows the city and guessed the digits, and the classic guess is the -000 that 957 municipalities never received. Answering that with a bare "not found" throws away what the API already knows: which municipality the number would have fallen under. The 404 now carries an optional faixa, and it is exposed the way geo already is — a derived type behind a logical flag on the address, because the API omits the block entirely rather than sending null. It stays a 404: found is still false and the status is still CEPIS_ERR_NOT_FOUND. The band is context for the failure, never an address. cep_ini and cep_fim are the smallest and largest CEP that actually exist there, not the bounds the Correios publish — the published start for Areal is 25845000, exactly the CEP that fails. The pair is not a list either: 118 CEPs over some 4,900 numbers, which is what ceps is for. Parsing is deliberately silent about every failure. A body that is not JSON, or a faixa that is absent, null, not an object or empty, leaves has_faixa false. Turning any of those into an invalid-response error would tell the caller to retry a CEP that will never exist. --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'README.md') diff --git a/README.md b/README.md index 7d6d6ab..c936ceb 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,55 @@ end select `cepis_status_name(status)` gives a short, stable English name for logging. +### When the CEP does not exist + +A CEP that fails is rarely a random number: it is usually someone who knows the +city and guessed the digits, and the classic guess is the `-000` that 957 +municipalities never received. So a 404 may carry a `faixa` naming the +municipality the CEP *would* have belonged to. It is on the address as +`has_faixa` / `faixa`, exactly like `has_geo` / `geo`: + +```fortran +call cepis_lookup('25845-000', a, status, message) + +if (status == CEPIS_ERR_NOT_FOUND .and. a%has_faixa) then + print *, a%faixa%localidade ! 'Areal' + print *, a%faixa%uf ! 'RJ' + print *, a%faixa%estado ! 'Rio de Janeiro' + print *, a%faixa%regiao ! 'Sudeste' + print *, a%faixa%ibge ! '3300225' + print *, a%faixa%formatted_cep_ini() ! '25845-001' + print *, a%faixa%formatted_cep_fim() ! '25849-899' + print *, a%faixa%ceps ! 118 +end if +``` + +> **It is still a 404.** `status` is `CEPIS_ERR_NOT_FOUND` and `a%found` is +> `.false.`. `faixa` is context for the error, never an address: the CEP does +> not exist and nothing there can be delivered to. + +Two things about `cep_ini` and `cep_fim`: + +- They are the **smallest and largest CEP that actually exist** in that + municipality, not the bounds the Correios publish. The DNE's own start for + Areal is `25845000` — precisely the CEP that just failed, which is why the + published bound would be no use here. +- **The range is sparse, and the pair is not a list.** Areal's 118 CEPs are + scattered over the ~4,900 numbers between `25845001` and `25849899`; almost + none of the numbers in between exist either. That is what `ceps` is for. + Show the range, never enumerate it, and check any single number with a + lookup. + +`has_faixa` is `.false.` whenever the API omits the block — it **omits it, it +never sends null** — which happens when the CEP falls in a band no municipality +owns. It is also `.false.` for a 404 whose body is malformed or unintelligible: +parsing the band can never turn a clean not-found into +`CEPIS_ERR_INVALID_RESPONSE`, because that would tell you to retry a CEP that +will never exist. + +Only `lookup` carries it. The batch behind `lookup_many` is CSV and has no +`faixa` column, so a CEP missing from a batch is just `found = .false.`. + `CEPIS_ERR_INVALID_RESPONSE` almost always means something between you and the API is answering instead of it — a captive Wi-Fi portal, a corporate proxy, an HTML error page. Useful as a diagnosis: the problem is not in your code. -- cgit v1.3