Importar um condomínio
Para registar um condomínio basta a morada. Em três chamadas obtém a referência do prédio, todas as suas habitações, lojas, garagens e arrecadações (com uso, área, coeficiente de participação, escada, piso e porta) e o detalhe de qualquer habitação. As respostas deste guia são reais, tiradas de produção.
1. Da morada ao prédio
GET /v1/search/address/candidates recebe a morada em texto livre (rua e número, município e, se o tiver, código postal) e devolve as entradas de prédio que correspondem, ordenadas por confiança, cada uma com a sua referência cadastral de 14 caracteres. Não depende do Catastro: geocodifica com o CartoCiudad (IGN) e completa com a nossa cópia do Catastro. Também aceita os campos em separado: street, number, municipality e postcode.
curl -G "https://api.parcelgps.com/v1/search/address/candidates" \
--data-urlencode "q=Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas" \
--data-urlencode "limit=3" \
-H "X-API-Key: $CATASTROGPS_API_KEY"Resposta real
200 OK{
"success": true,
"data": {
"query": {
"text": "Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas",
"street": "Avenida José Rodríguez de la Borbolla Camoyán",
"number": 10,
"municipality": "Dos Hermanas"
},
"candidates": [
{
"reference": "0745901TG4304N",
"country": "ES",
"address": "AVENIDA JOSE RGUEZ BORBOLLA CAMOY 10",
"number": 10,
"postalCode": "41704",
"municipality": "Dos Hermanas",
"region": "Sevilla",
"latitude": 37.31947088654626,
"longitude": -5.926788955974699,
"confidence": 0.93,
"numberMatches": true,
"municipalityMatches": true,
"inOwnCopy": true,
"cadastreAddress": "AV JOSE RGUEZ BORBOLLA CAMOY 10",
"use": "Residencial",
"dwellings": 346,
"yearBuilt": 2023
},
{
"reference": "0747201TG4304N",
"country": "ES",
"address": "BULEVAR JOSE RODRIGUEZ DE LA BORBOLLA CAMOYAN 11",
"number": 11,
"confidence": 0.55,
"numberMatches": false,
"municipalityMatches": true,
"inOwnCopy": true
}
],
"attribution": "CartoCiudad (Instituto Geográfico Nacional) y Dirección General del Catastro"
},
"remainingSearches": 2894
}- Com confiança de 0,75 ou mais coincidem o número e o município: pode importar sem perguntar. Abaixo disso, mostre os candidatos ao utilizador para que escolha.
- No País Basco e em Navarra o candidato chega com country PV ou NA e a referência foral: o passo 2 aceita-a com country=PV ou NA e lista as unidades a partir da cópia do respetivo cadastro foral, sem coeficiente de participação (os dados abertos forais não o publicam).
2. Todas as unidades do prédio
GET /v1/parcels/:reference14/units devolve as unidades em páginas de até 200, ordenadas por referência. Enquanto truncated for true, repita a chamada com cursor igual a nextCursor. propertyUnitCount indica logo na primeira página quantas existem no total.
curl -i "https://api.parcelgps.com/v1/parcels/0745901TG4304N/units" \
-H "X-API-Key: $CATASTROGPS_API_KEY"
curl -i "https://api.parcelgps.com/v1/parcels/0745901TG4304N/units?cursor=0745901TG4304N0201MZ" \
-H "X-API-Key: $CATASTROGPS_API_KEY"Resposta real
200 OKHTTP/2 200
etag: "5ab6bd3d95f85dddba81818bcb0cb65e"
cache-control: private, max-age=21600
x-quota-remaining: 2893
{
"success": true,
"data": {
"reference": "0745901TG4304N",
"address": "AV JOSE RGUEZ BORBOLLA CAMOY 10",
"postalCode": "41704",
"municipality": "DOS HERMANAS",
"region": "Sevilla",
"mainUse": "Residencial",
"totalArea": 32789,
"yearBuilt": 2023,
"unitCount": 200,
"propertyUnitCount": 365,
"units": [
{
"reference": "0745901TG4304N0002KH",
"staircase": "",
"floor": "01",
"door": "B",
"use": "Residencial",
"area": 155,
"description": "Planta 01, Pta. B - Residencial",
"ownershipShare": 0.279543,
"yearBuilt": 2023,
"address": "AV JOSE RGUEZ BORBOLLA CAMOY 10 Pl:01 Pt:B"
},
{
"reference": "0745901TG4304N0003LJ",
"staircase": "",
"floor": "01",
"door": "C",
"use": "Residencial",
"area": 163,
"description": "Planta 01, Pta. C - Residencial",
"ownershipShare": 0.293879,
"yearBuilt": 2023,
"address": "AV JOSE RGUEZ BORBOLLA CAMOY 10 Pl:01 Pt:C"
}
],
"truncated": true,
"nextCursor": "0745901TG4304N0201MZ",
"dataSource": "clone",
"dataDate": "2026-01-23",
"attribution": "Dirección General del Catastro"
},
"remainingSearches": 2893
}- Um prédio de 365 unidades são duas chamadas: 200 e 165. O cursor é estável, por isso pode retomar uma importação interrompida.
- Por unidade: reference (20 caracteres), use, area (m²), ownershipShare (coeficiente em %, número com toda a precisão), staircase, floor, door, ano e morada.
- dataSource clone significa que vem da nossa cópia do Catastro, sem depender de o Catastro estar operacional; dataDate é a publicação do Catastro de onde vêm as linhas. Se um prédio não estiver na cópia, o Catastro é consultado em direto (dataSource catastro).
3. O detalhe de uma habitação
GET /v1/parcels/:reference20 devolve uma habitação concreta com os mesmos campos da listagem, além das coordenadas, do contorno e da área da parcela.
curl "https://api.parcelgps.com/v1/parcels/0745901TG4304N0002KH" \
-H "X-API-Key: $CATASTROGPS_API_KEY"Resposta real
200 OK{
"success": true,
"data": {
"reference": "0745901TG4304N0002KH",
"country": "ES",
"address": "AV JOSE RGUEZ BORBOLLA CAMOY 10 Pl:01 Pt:B",
"postalCode": "41704",
"municipality": "DOS HERMANAS",
"region": "Sevilla",
"latitude": 37.3194709,
"longitude": -5.926789,
"use": "Residencial",
"landClass": "Urbano",
"builtArea": 155,
"parcelArea": 7320,
"yearBuilt": 2023,
"ownershipShare": 0.279543,
"floor": "01",
"door": "B",
"fromOwnCopy": true
},
"remainingSearches": 2892
}- ownershipShare, staircase, floor e door têm o mesmo nome que na listagem. builtArea aqui é area na listagem.
Reimportar sem gastar quota
Cada página de unidades e cada pesquisa de morada trazem ETag. Guarde o ETag de cada página e envie-o em If-None-Match na vez seguinte: se nada mudou, a resposta é 304 sem corpo e não gasta quota.
curl -i "https://api.parcelgps.com/v1/parcels/0745901TG4304N/units" \
-H "X-API-Key: $CATASTROGPS_API_KEY" \
-H 'If-None-Match: "5ab6bd3d95f85dddba81818bcb0cb65e"'
HTTP/2 304
x-quota-remaining: 2929O fluxo completo, com paginação, novas tentativas e ETag
Repete os 429 e 503 que trazem Retry-After, lança os restantes erros com o respetivo code e reutiliza as páginas que não mudaram.
const BASE = "https://api.parcelgps.com/v1";
const KEY = process.env.CATASTROGPS_API_KEY;
async function call(path, etag) {
for (let attempt = 0; attempt < 5; attempt++) {
const headers = { "X-API-Key": KEY };
if (etag) headers["If-None-Match"] = etag;
const res = await fetch(BASE + path, { headers });
if (res.status === 304) return { data: null, etag };
const retryAfter = res.headers.get("Retry-After");
if ((res.status === 429 || res.status === 503) && retryAfter) {
await new Promise((resolve) => setTimeout(resolve, Number(retryAfter) * 1000));
continue;
}
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.code}: ${body.message}`);
return { data: body.data, etag: res.headers.get("ETag") };
}
throw new Error("retries exhausted");
}
export async function findBuilding(address) {
const { data } = await call("/search/address/candidates?q=" + encodeURIComponent(address));
const best = data.candidates[0];
if (best.confidence < 0.75) throw new Error("Ambiguous address: ask the user to pick a candidate");
return best.reference;
}
export async function importUnits(reference14, pages = new Map()) {
const units = [];
let cursor = "";
for (;;) {
const cached = pages.get(cursor);
const query = cursor ? "?cursor=" + cursor : "";
const { data, etag } = await call(`/parcels/${reference14}/units${query}`, cached?.etag);
const page = data ?? cached.data;
pages.set(cursor, { etag, data: page });
units.push(...page.units);
if (!page.truncated) return { units, pages };
cursor = page.nextCursor;
}
}
const reference14 = await findBuilding("Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas");
const { units, pages } = await importUnits(reference14);
console.log(reference14, units.length);Quanto custa
| Chamada | Unidades de quota |
|---|---|
| GET /v1/search/address/candidates | 1 por pesquisa com resultados. |
| GET /v1/parcels/:reference14/units | 1 por cada unidade da página (mínimo 1). Uma página de 200 são 200. |
| GET /v1/parcels/:reference | 1 por habitação. |
| 304 / 4xx / 5xx | Grátis: nem um 304 nem um erro gastam quota. |
Exemplo: um condomínio de 365 unidades custa 1 (morada) + 200 + 165 (duas páginas) = 366 unidades. Reimportá-lo sem alterações custa 0.
Erros
| HTTP | Código | O que significa e o que fazer |
|---|---|---|
| 304 | - | Nada mudou desde o seu ETag. Use o que já tinha. Grátis. |
| 400 | VALIDATION_ERROR | Parâmetros mal formados (morada vazia, código postal sem 5 dígitos, cursor que não é desse prédio). Corrija o pedido. |
| 401 | KEY_AUTH_001 / 002 / 003 | Falta a API key ou não é válida. |
| 404 | NOT_FOUND | A morada ou a referência não existem. Nunca é usado para falhas do Catastro. |
| 429 | KEY_RATE_002 | Ultrapassou os pedidos por minuto da sua chave. Aguarde os segundos de Retry-After. |
| 429 | KEY_AUTH_004 | Quota e saldo esgotados (veja X-Quota-Remaining e X-Quota-Reset): carregue saldo no portal ou aguarde a reposição do dia 1. |
| 503 | SERVICE_UNAVAILABLE | A fonte oficial (Catastro ou CartoCiudad) está em baixo ou saturada e a nossa cópia não tem o dado. Tente de novo após Retry-After. Grátis. |
{
"success": false,
"code": "NOT_FOUND",
"message": "No building entrance (portal) with a cadastral reference matches that address. Include the street number and the municipality."
}Referência completa
Todos os endpoints, campos e códigos estão na especificação OpenAPI 3.1, que pode importar no Postman, no Insomnia ou num gerador de clientes: https://api.parcelgps.com/v1/openapi.json