API d'import pour agences
Envoyez des annonces vers Seeki via API.
Importez en masse les annonces immobilières de votre CRM ou de votre logiciel de gestion. Un seul endpoint, un statut par élément, un TTL automatique.
Obtenir une clé API
L'accès à l'API d'import agence requiert un abonnement agence Seeki actif. Chaque abonnement inclut une clé API limitée à votre compte d'agence.
Abonnez-vous sur la page Pour les agents pour commencer.
Authentification
Chaque requête doit inclure votre clé API sous forme de jeton Bearer dans l'en-tête Authorization.
Authorization: Bearer seeki_live_your_key_hereLes clés commençant par seeki_live_ sont des clés de production. Les clés de staging commencent par seeki_test_. Elles ne sont pas interchangeables entre les environnements.
Votre première importation
Envoyez une requête POST à /v1/listings avec un corps JSON contenant un tableau listings. Chaque élément représente un bien.
curl -X POST https://ingest.seeki.eu/v1/listings \
-H "Authorization: Bearer seeki_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"listings": [
{
"external_id": "crm-listing-00123",
"listing_type": "SELL",
"real_estate_type": "APARTMENT",
"price": 320000,
"currency": "EUR",
"address": {
"street": "Wenceslas Square 1",
"city": "Prague",
"country_code": "CZ",
"postal_code": "11000"
},
"name": "Sunny 2-bedroom apartment, Wenceslas Square",
"floorage": 65
}
]
}'Un lot traité avec succès renvoie un HTTP 200 avec les tableaux accepted et rejected :
{
"accepted": [
{ "external_id": "crm-listing-00123", "import_item_id": "uuid-…" }
],
"rejected": []
}Structure de la requête
Le corps de premier niveau est { listings: [...] }. Champs requis par annonce :
| Champ | Obligatoire ? | Notes |
|---|---|---|
| external_id | Obligatoire | Your CRM’s unique ID. Used for idempotent re-imports and deduplication. |
| listing_type | Obligatoire | SELL ou RENT. |
| real_estate_type | Obligatoire | APARTMENT, HOUSE, LAND, COMMERCIAL ou OTHER. |
| price | Obligatoire | Numérique. Utilisez le champ currency pour le code ISO 4217 (EUR par défaut). |
| address OR coordinates | Obligatoire | Fournissez soit un objet address (street, city, country_code), soit des coordonnées ({ lat, lng }). Au moins l'un des deux doit être présent. |
| currency | Facultatif | Code ISO 4217, par exemple EUR, CZK, PLN. EUR par défaut. |
| name, description | Facultatif | Titre de l'annonce et description en texte libre. |
| floorage, floor, rooms | Facultatif | Surface du bien en m², numéro d'étage et nombre de pièces. |
| images | Facultatif | Tableau d'URL d'images publiques. Le worker d'import les récupère et les met en cache. |
| contact | Facultatif | Nom, e-mail et téléphone de l'agent pour le routage des demandes. |
Consultez le schéma complet avec tous les champs optionnels dans la référence API interactive.
Structure de la réponse et erreurs
L'endpoint /v1/listings renvoie toujours un HTTP 200 OK tant que la requête elle-même est correctement formée (JSON valide, en-tête d'authentification correct, taille respectée). Les échecs au niveau d'une annonce sont signalés dans le tableau rejected — pas via des codes d'erreur HTTP.
Chaque élément rejected contient external_id, error_code et un message lisible. Les erreurs au niveau du lot (auth invalide, charge utile trop volumineuse) renvoient un statut HTTP non-200 avec un error_code de premier niveau.
Codes d'erreur
Les codes au niveau du lot renvoient des erreurs HTTP. Les codes par élément apparaissent dans le tableau rejected d'une réponse 200.
| error_code | HTTP / portée | Signification |
|---|---|---|
| MISSING_AUTHORIZATION | 401 | Aucun en-tête Authorization n'a été envoyé. |
| INVALID_KEY | 401 | La clé est introuvable, a été révoquée ou a expiré. |
| SUBSCRIPTION_INACTIVE | 403 | The agency’s subscription is not active or past_due. |
| PAYLOAD_TOO_LARGE | 413 | Le corps de la requête dépasse la limite de 25 Mo. |
| TOO_MANY_ITEMS | 413 | Le tableau listings contient plus de 5 000 éléments. |
| VALIDATION_FAILED | par élément | Un ou plusieurs champs requis sont absents ou ont une valeur invalide. Consultez le champ message pour plus de détails. |
| GEOCODE_ADDRESS_NOT_FOUND | par élément | L'adresse fournie n'a pas pu être convertie en coordonnées. Vérifiez street, city et country_code. |
| GEOCODE_COORDINATES_INVALID | par élément | Les valeurs lat/lng fournies sont hors plages valides (lat ±90, lng ±180). |
| INFRA_QUEUE_REJECTED | par élément | La file du workflow a rejeté l'élément, généralement en raison d'une surcharge transitoire. Réessayez après un court délai. |
| INFRA_LOST | par élément | Le workflow a été accepté mais son résultat n'a jamais été enregistré. Utilisez l'endpoint de relance. |
| INTERNAL_ERROR | par élément | Une erreur serveur inattendue s'est produite. Une nouvelle tentative peut aboutir ; contactez le support si le problème persiste. |
Idempotence / ré-importations
Re-posting a listing with the same external_id updates the existing record — it does not create a duplicate. The listing’s TTL is refreshed on every successful import.
En interne, chaque élément importé correspond à un Cloudflare Workflow dont l'ID est :
agency-{agency_id}-{external_id}Expiration des annonces
Chaque annonce importée a un TTL de 60 jours à compter du dernier import réussi. Une fois le TTL expiré, l'annonce est automatiquement dépubliée par une tâche cron quotidienne.
Pour maintenir une annonce en ligne indéfiniment, ré-importez-la (même avec des données identiques) avant la fin de la fenêtre de 60 jours. Mettre en place une re-synchronisation nocturne de vos annonces actives est le schéma recommandé.
Statut + nouvelle tentative
Utilisez GET /v1/import-items/{import_item_id}/status pour interroger l'état de traitement d'un élément. L'import_item_id est renvoyé dans le tableau accepted de la réponse POST initiale.
curl https://ingest.seeki.eu/v1/import-items/{import_item_id}/status \
-H "Authorization: Bearer seeki_live_your_key_here"{
"import_item_id": "uuid-…",
"external_id": "crm-listing-00123",
"status": "completed",
"listing_id": "uuid-listing"
}Si un élément se retrouve dans l'état INFRA_LOST ou INFRA_QUEUE_REJECTED, remettez-le en file sans renvoyer le lot complet :
curl -X POST https://ingest.seeki.eu/v1/import-items/{import_item_id}/retry \
-H "Authorization: Bearer seeki_live_your_key_here"Limites
- Taille du corps : 25 Mo maximum par requête.
- Éléments par requête : 5 000 maximum. Divisez les lots plus grands.
- Aucune limite de QPS n'est appliquée actuellement. Les très grosses rafales peuvent être limitées automatiquement ; répartissez les synchronisations à fort volume sur plusieurs requêtes.
Mise en production
Il existe deux environnements distincts. Les clés API sont liées à un environnement — une clé de production ne fonctionnera pas en staging, et inversement.
| Environnement | URL de base |
|---|---|
| Staging | https://ingest.seeki.store/v1 |
| Production | https://ingest.seeki.eu/v1 |
Tous les endpoints (/listings, /import-items/{id}/status, /import-items/{id}/retry) sont identiques sur les deux environnements.
Prêt à intégrer ?
Ouvrez la référence interactive pour explorer tous les champs, tester des requêtes dans le navigateur et télécharger le JSON Schema pour votre validateur.