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 OK
HTTP/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: 2929

O 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

ChamadaUnidades de quota
GET /v1/search/address/candidates1 por pesquisa com resultados.
GET /v1/parcels/:reference14/units1 por cada unidade da página (mínimo 1). Uma página de 200 são 200.
GET /v1/parcels/:reference1 por habitação.
304 / 4xx / 5xxGrá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

HTTPCódigoO que significa e o que fazer
304-Nada mudou desde o seu ETag. Use o que já tinha. Grátis.
400VALIDATION_ERRORParâmetros mal formados (morada vazia, código postal sem 5 dígitos, cursor que não é desse prédio). Corrija o pedido.
401KEY_AUTH_001 / 002 / 003Falta a API key ou não é válida.
404NOT_FOUNDA morada ou a referência não existem. Nunca é usado para falhas do Catastro.
429KEY_RATE_002Ultrapassou os pedidos por minuto da sua chave. Aguarde os segundos de Retry-After.
429KEY_AUTH_004Quota e saldo esgotados (veja X-Quota-Remaining e X-Quota-Reset): carregue saldo no portal ou aguarde a reposição do dia 1.
503SERVICE_UNAVAILABLEA 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