Tenir un miroir à jour
La plupart des intégrations finissent par conserver une copie d'une partie du catalogue. Le faire mal est l'erreur la plus coûteuse que propose cette API, et elle prend trois formes reconnaissables : tout relire à intervalle régulier, paginer par décalage, et traiter une fiche absente comme une fiche supprimée.
La forme qui fonctionne
- Faites un remplissage initial. Parcourez le filtre qui vous intéresse du premier curseur au dernier, en stockant les fiches au fur et à mesure.
- Notez la ligne de flottaison. Gardez le
updated_atle plus récent que vous ayez vu, pas l'heure d'exécution de votre traitement. Ce sont deux choses différentes, et c'est dans cet écart que des fiches se perdent. - Interrogez les changements. Demandez
updated_sincequelques minutes avant cette marque. - Ou cessez d'interroger. Les webhooks suppriment entièrement cette boucle, et ne coûtent pas de quota.
import { Skautik } from "@skautik/sdk";
const skautik = new Skautik({ apiKey: process.env.SKAUTIK_API_KEY! });
async function backfill(city: string) {
let newest = "";
for await (const property of skautik.properties.listAll({ city })) {
await upsert(property);
if (property.updatedAt > newest) {
newest = property.updatedAt;
}
}
return newest;
}L'itérateur suit le curseur pour vous et s'arrête sur has_more, la
seule condition correcte. Écrire la boucle à la main, c'est là qu'on s'arrête sur une page
courte, alors qu'une page pleine peut être la dernière.
Faites chevaucher la fenêtre
Demandez quelques minutes avant votre ligne de flottaison, pas la marque elle-même :
GET /v1/api/properties?city=Berlin&updated_since=2026-08-11T03:55:00ZLes fiches sont écrites de façon concurrente. Une frontière stricte manque tout ce qui a été validé un instant après votre coupure mais horodaté un instant avant, et cette fiche reste manquante jusqu'à ce qu'elle change à nouveau par hasard. Traiter deux fois la même fiche ne coûte rien si votre écriture est un upsert ; en manquer une vous coûte une réponse fausse pendant une durée indéterminée.
L'absence n'est pas une suppression
Une fiche qui cesse d'apparaître dans une liste filtrée n'a pas nécessairement disparu. Elle
peut avoir changé d'une manière qui la fait sortir de votre filtre : une hausse de prix au-delà de
votre max_price, un changement de quartier, un retrait.
Le retrait est explicite. Un bien retiré garde son identifiant et reste
lisible par id ; le statut de son annonce indique archived ou sold. Il quitte la
liste par défaut parce que le défaut porte sur les annonces actives, pas parce qu'il a cessé
d'exister.
Donc : ne déduisez jamais une suppression d'une absence. Soit vous vous abonnez à property.withdrawn,
soit vous demandez le statut explicitement quand vous avez besoin de savoir :
GET /v1/api/properties?city=Berlin&status=archivedSi votre miroir supprime tout ce qui sort d'une page filtrée, un seul changement de prix supprimera un bien encore sur le marché.
Quoi stocker
Stockez au minimum l'identifiant et le updated_at. L'identifiant est opaque
et stable ; l'horodatage est ce qui rend la synchronisation suivante peu coûteuse.
Stockez aussi external_id si vous êtes également la source de la fiche. C'est votre propre
identifiant renvoyé, et c'est ce qui vous permet de rapprocher sans tenir une
table de correspondance entre nos identifiants et les vôtres.
Coût
| Approche | Requêtes par jour, 20 000 biens |
|---|---|
| Relecture horaire, 200 par page | 2 400 |
updated_since toutes les heures | 24 à 50, selon la rotation |
| Webhooks | 0 |
La première ligne est la raison d'être des quotas. La troisième est la raison d'être des webhooks.
Quand un remplissage est le mauvais outil
Des lectures soutenues et volumineuses de tout le catalogue sont mieux servies par un export que par une exploration plus rapide. Un export est une seule requête, produit un seul fichier, et n'entre pas en concurrence avec votre trafic de production pour la limite de rafale. Demandez-nous avant de construire quelque chose qui pagine tout le marché chaque nuit.