Skip to main content
Seeki.eu

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.

L'interface de gestion des clés (consultation, rotation, révocation) sera disponible dans une prochaine mise à jour du tableau de bord. Pour l'instant, votre clé API est envoyée par e-mail à l'activation de votre abonnement. Contactez info@seeki.eu si vous avez besoin d'une nouvelle clé.

Authentification

Chaque requête doit inclure votre clé API sous forme de jeton Bearer dans l'en-tête Authorization.

HTTP header
Authorization: Bearer seeki_live_your_key_here

Les 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
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 :

200 OK
{
  "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 :

ChampObligatoire ?Notes
external_idObligatoireYour CRM’s unique ID. Used for idempotent re-imports and deduplication.
listing_typeObligatoireSELL ou RENT.
real_estate_typeObligatoireAPARTMENT, HOUSE, LAND, COMMERCIAL ou OTHER.
priceObligatoireNumérique. Utilisez le champ currency pour le code ISO 4217 (EUR par défaut).
address OR coordinatesObligatoireFournissez soit un objet address (street, city, country_code), soit des coordonnées ({ lat, lng }). Au moins l'un des deux doit être présent.
currencyFacultatifCode ISO 4217, par exemple EUR, CZK, PLN. EUR par défaut.
name, descriptionFacultatifTitre de l'annonce et description en texte libre.
floorage, floor, roomsFacultatifSurface du bien en m², numéro d'étage et nombre de pièces.
imagesFacultatifTableau d'URL d'images publiques. Le worker d'import les récupère et les met en cache.
contactFacultatifNom, 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_codeHTTP / portéeSignification
MISSING_AUTHORIZATION401Aucun en-tête Authorization n'a été envoyé.
INVALID_KEY401La clé est introuvable, a été révoquée ou a expiré.
SUBSCRIPTION_INACTIVE403The agency’s subscription is not active or past_due.
PAYLOAD_TOO_LARGE413Le corps de la requête dépasse la limite de 25 Mo.
TOO_MANY_ITEMS413Le tableau listings contient plus de 5 000 éléments.
VALIDATION_FAILEDpar élémentUn ou plusieurs champs requis sont absents ou ont une valeur invalide. Consultez le champ message pour plus de détails.
GEOCODE_ADDRESS_NOT_FOUNDpar élémentL'adresse fournie n'a pas pu être convertie en coordonnées. Vérifiez street, city et country_code.
GEOCODE_COORDINATES_INVALIDpar élémentLes valeurs lat/lng fournies sont hors plages valides (lat ±90, lng ±180).
INFRA_QUEUE_REJECTEDpar élémentLa 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_LOSTpar élémentLe workflow a été accepté mais son résultat n'a jamais été enregistré. Utilisez l'endpoint de relance.
INTERNAL_ERRORpar élémentUne 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 :

Workflow ID pattern
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.

GET /import-items/{id}/status
curl https://ingest.seeki.eu/v1/import-items/{import_item_id}/status \
  -H "Authorization: Bearer seeki_live_your_key_here"
Response
{
  "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 :

POST /import-items/{id}/retry
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.

EnvironnementURL de base
Staginghttps://ingest.seeki.store/v1
Productionhttps://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.

Nous utilisons des cookies pour améliorer votre expérience sur notre site. Politique de Confidentialité