fonciqAPI

Comment extraire l'index des immeubles via l'API

Guide pas à pas : commander un index, suivre la tâche, lire les lignes en JSON ou en CSV. Exemples cURL, Python et Node.

Ouvrir

Un index des immeubles se commande, se suit puis se lit en trois appels. Chaque inscription de l'index devient une ligne structurée (numéro d'inscription, date de présentation, nature, parties, radiations telles qu'inscrites). Le PDF source est toujours renvoyé avec les lignes, et il fait foi.

Cette page est un guide de l'API. La présentation de l'API Fonciq, ses opérations et ses limites publiées sont sur fonciq.ca.

Prérequis

1. Commander l'index

POST /v1/registre/requests (portée registre:write) exige un en-tête Idempotency-Key, conservé 24 heures. Une reprise avec la même clé renvoie la même réponse.

curl -X POST https://api.fonciq.ca/v1/registre/requests \
  -H "Authorization: Bearer $FONCIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c0b2e-7a4d-4e1a-9c2b-0d5e6f7a8b9c" \
  -d '{"lot":"1234567","documents":["index"]}'

La réponse est 202 :

{ "job_id": "job_01HZX", "account_id": "rfa_exemple" }

2. Suivre la tâche

La consultation est asynchrone. GET /v1/jobs/{id} (portée jobs:read) donne l'état : queued, capacity_wait, running, succeeded ou failed. L'état capacity_wait signifie que le plafond du jour du compte retient encore l'envoi au Registre. La capacité du compte se lit dans la même réponse.

curl https://api.fonciq.ca/v1/jobs/job_01HZX \
  -H "Authorization: Bearer $FONCIQ_API_KEY"

Interrogez à intervalle raisonnable : la clé est limitée à 60 requêtes par minute (Limites de débit).

3. Lire les lignes

Lorsque la tâche est succeeded, le résultat est sur result.index (un bloc par lot pour un lot groupé). Il donne pdf_url, entries_url et entries. Les mêmes lignes se lisent directement avec GET /v1/documents/{id}/entries, en JSON par défaut ou en CSV avec format=csv.

curl "https://api.fonciq.ca/v1/documents/42/entries?format=csv" \
  -H "Authorization: Bearer $FONCIQ_API_KEY"

Le PDF source se télécharge avec GET /v1/documents/{id}.

Python

import os, time, uuid, requests

BASE = "https://api.fonciq.ca"
HEADERS = {"Authorization": f"Bearer {os.environ['FONCIQ_API_KEY']}"}

job = requests.post(
    f"{BASE}/v1/registre/requests",
    headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
    json={"lot": "1234567", "documents": ["index"]},
).json()

while True:
    state = requests.get(f"{BASE}/v1/jobs/{job['job_id']}", headers=HEADERS).json()
    if state["status"] in ("succeeded", "failed"):
        break
    time.sleep(10)

if state["status"] == "succeeded":
    for entry in state["result"]["index"]["entries"]:
        print(entry["inscription"], entry["presentation_date"], entry["nature"])

Node

const BASE = 'https://api.fonciq.ca';
const headers = { Authorization: `Bearer ${process.env.FONCIQ_API_KEY}` };

const created = await fetch(`${BASE}/v1/registre/requests`, {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
  body: JSON.stringify({ lot: '1234567', documents: ['index'] }),
}).then((r) => r.json());

let job;
do {
  await new Promise((resolve) => setTimeout(resolve, 10_000));
  job = await fetch(`${BASE}/v1/jobs/${created.job_id}`, { headers }).then((r) => r.json());
} while (!['succeeded', 'failed'].includes(job.status));

if (job.status === 'succeeded') {
  for (const entry of job.result.index.entries) console.log(entry.inscription, entry.nature);
}

Ce que contiennent les lignes

ChampContenu
inscriptionNuméro d'inscription, espaces conservés.
presentation_dateDate de présentation, YYYY-MM-DD.
natureNature de l'acte. Nulle lorsque la colonne n'a pas été lue.
parties{ "role", "name" }, lorsque la qualité est reconnue.
radiationsMentions de radiation telles qu'inscrites : inscription, mention, raw_text.
confidenceToujours le littéral unscored : l'analyseur actuel ne produit pas de score. Laissez unscored.
source_document_idIdentifiant du PDF source.

Le PDF fait foi. Une liste entries vide est une lecture vide : aucune ligne n'est inventée pour la remplir, et les rangées sans date ou sans numéro d'inscription sont écartées. Le détail de chaque champ est dans Tâches et résultats. Les colonnes du CSV sont les mêmes pour jobs/{id}/results, lots/{lot} et documents/{id}/entries.

Coût

Chaque index livré coûte 0,99 $ excluant frais du registre. L'index consulte toujours le Registre, qui facture 1,50 $ au titulaire du compte : un index consulté coûte donc 2,49 $ au total. Les frais du Registre ne sont pas un débit Fonciq. Une clé fq_test_ ne débite pas. Voir Coûts.

Erreurs fréquentes

CodeCause
401Clé absente, révoquée ou sans la portée registre:write ou jobs:read.
400Corps invalide, ou format autre que csv sur une lecture de lignes.
409Aucun compte du Registre : rf_account_required.
404Document qui n'est pas un index produit pour votre organisation.
429Plus de 60 requêtes par minute (rate_limited) : attendez le délai de Retry-After.

Le corps d'erreur est le même partout : voir Erreurs.

Pour aller plus loin

Sur cette page