fonciqAPI
EnGuides

Be told about a new filing on a lot

Create a daily or weekly watch and receive a signed webhook (HMAC-SHA256) when a filing is added to a lot's index.

Ouvrir

The Registre foncier has no push feed. A Fonciq watch is therefore a scheduled re-check of a lot, compared with a reference snapshot taken when the watch is created. When a difference appears, Fonciq calls your URL with a signed webhook. An empty difference sends nothing.

This page is a guide. The complete reference is Surveillances et webhooks (French).

1. Create the watch

POST /v1/watches (scope watches:write) requires an Idempotency-Key header.

curl -X POST https://api.fonciq.ca/v1/watches \
  -H "Authorization: Bearer $FONCIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5d0b7c3a-2e1f-4b6a-8c9d-1a2b3c4d5e6f" \
  -d '{"lot":"1234567","cadence":"daily","url":"https://exemple.com/hooks/fonciq"}'

cadence is weekly (the default) or daily. There is no monthly cadence. Without account_id, the watch is placed on the default Registre account; it uses that account's daily index capacity (cap of 540 indexes per day, 180 of them reserved for on-demand calls). An organisation can have 25 active watches (409 with watch_cap_reached beyond that).

Creating the watch costs CAD 0.99 excluding Registre fees. Each index re-checked afterwards is a separate call: CAD 0.99 excluding Registre fees, plus the CAD 1.50 Registre fee charged to the account holder.

Pausing, deleting, history and manual resend are done in Studio › Développeurs: they are not public routes.

2. Event types

typeWhen
index.inscription_addedA registration number absent from the reference snapshot appears.
acte.addedThe PDF of that filing's deed is obtained.
cadastre.changedThe lot number, the cadastre label or the geometric identity changed.
assessment.changedThe MAMH roll year or the assessed amount changed.

Body of an index.inscription_added notice:

{
  "id": "evt_01HZX",
  "type": "index.inscription_added",
  "account_id": "rfa_exemple",
  "lot": "1234567",
  "change": "Inscription 21 014 436",
  "old": { "inscriptions": [] },
  "new": { "inscriptions": ["21 014 436"] },
  "document_url": "https://api.fonciq.ca/v1/documents/42"
}

document_url is the index PDF, the authoritative record. Structured rows are read with GET /v1/documents/{id}/entries.

3. Verify the signature

Each notice carries the header Fonciq-Signature: t=<unix>,v1=<hex>. v1 is the HMAC-SHA256 of {t}.{raw body}, signed with the endpoint secret, shown once. Reject a t more than five minutes from your clock, and compare the raw body, before any JSON rewriting.

Node

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const age = Math.abs(Math.floor(Date.now() / 1000) - Number(parts.t));
  if (!parts.t || !parts.v1 || age > 300) return false;
  const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1);
  return a.length === b.length && timingSafeEqual(a, b);
}

Python

import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(item.split("=", 1) for item in header.split(","))
    if "t" not in parts or "v1" not in parts or abs(time.time() - int(parts["t"])) > 300:
        return False
    signed = parts["t"].encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

4. Respond, and retries

Answer 2xx quickly. A notice that fails is retried: immediate delivery, then about 24 h, 48 h and 72 h later. The notice then moves to failed. A manual resend from the dashboard is a new attempt.

See also

Sur cette page