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.
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
type | When |
|---|---|
index.inscription_added | A registration number absent from the reference snapshot appears. |
acte.added | The PDF of that filing's deed is obtained. |
cadastre.changed | The lot number, the cadastre label or the geometric identity changed. |
assessment.changed | The 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
- Surveillances et webhooks (French): caps, capacity and the full reference.