# Être avisé d'une nouvelle inscription sur un lot

Créez une surveillance quotidienne ou hebdomadaire et recevez un webhook signé (HMAC-SHA256) lorsqu'une inscription s'ajoute à l'index d'un lot.

Le Registre foncier n'offre pas de flux poussé. Une surveillance de l'API Fonciq est donc une **revérification planifiée** d'un lot, comparée à un instantané de référence pris à la création. Lorsqu'un écart apparaît, Fonciq appelle votre URL avec un webhook signé. Un écart vide n'envoie rien.

Cette page est un guide. La référence complète est dans [Surveillances et webhooks](/donnees/surveillances).

## 1. Créer la surveillance

`POST /v1/watches` (portée `watches:write`) exige un en-tête `Idempotency-Key`.

```bash
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` vaut `weekly` (par défaut) ou `daily`. Il n'y a pas de cadence mensuelle. Sans `account_id`, la surveillance est placée sur le compte du Registre par défaut ; elle consomme la capacité quotidienne d'index de ce compte (plafond de 540 index par jour, dont 180 réservés aux appels à la demande). Une organisation peut avoir 25 surveillances actives (`409` avec `watch_cap_reached` au-delà).

Créer la surveillance coûte 0,99 $ excluant frais du registre. Chaque index revérifié ensuite est un appel distinct : 0,99 $ excluant frais du registre, plus 1,50 $ de frais du Registre facturés au titulaire du compte.

La pause, la suppression, l'historique et le renvoi manuel se font dans [Studio › Développeurs](https://fonciq.ca/studio/developpeurs) : ce ne sont pas des routes publiques.

## 2. Types d'événements

| `type` | Moment |
| --- | --- |
| `index.inscription_added` | Un numéro d'inscription absent de l'instantané de référence apparaît. |
| `acte.added` | Le PDF de l'acte de cette inscription est obtenu. |
| `cadastre.changed` | Le numéro de lot, le libellé de cadastre ou l'identité géométrique a changé. |
| `assessment.changed` | L'année de rôle du MAMH ou le montant évalué a changé. |

Corps d'un avis `index.inscription_added` :

```json
{
  "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` est le PDF de l'index : il fait foi. Les lignes structurées se lisent avec `GET /v1/documents/{id}/entries`.

## 3. Vérifier la signature

Chaque avis porte l'en-tête `Fonciq-Signature: t=<unix>,v1=<hex>`. `v1` est le HMAC-SHA256 de `{t}.{corps brut}`, signé avec le secret du point de terminaison, montré une seule fois. Rejetez un `t` éloigné de plus de cinq minutes de votre horloge, et comparez le corps brut, avant toute réécriture JSON.

### Node

```js
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

```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. Répondre et reprises

Répondez `2xx` rapidement. Un avis qui échoue est réessayé : envoi immédiat, puis environ **24 h**, **48 h** et **72 h** plus tard. L'avis passe ensuite à `failed`. Le renvoi manuel, dans le tableau de bord, est un nouvel essai.

## À voir aussi

- [Surveillances et webhooks](/donnees/surveillances) : plafonds, capacité et référence complète.
- [Créer une surveillance](/donnees/api/surveillances/createWatch) et [l'avis webhook](/donnees/api/surveillances/webhookEvent) dans la référence de l'API.
