API Importazione Agenzie
Inserisca annunci in Seeki tramite API.
Importi in blocco gli annunci immobiliari dal suo CRM o sistema di gestione immobiliare. Un solo endpoint, stato per ogni elemento, TTL automatico.
Ottenere una chiave API
L'accesso all'API di importazione agenzia richiede un abbonamento agenzia Seeki attivo. Ogni abbonamento include una chiave API associata al suo account agenzia.
Si abboni nella pagina For Agents per iniziare.
Autenticazione
Ogni richiesta deve includere la sua chiave API come token Bearer nell'header Authorization.
Authorization: Bearer seeki_live_your_key_hereLe chiavi che iniziano con seeki_live_ sono chiavi di produzione. Le chiavi di staging iniziano con seeki_test_. Non sono interscambiabili tra ambienti.
La sua prima importazione
Invii una richiesta POST a /v1/listings con un corpo JSON contenente un array listings. Ogni elemento rappresenta un immobile.
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 batch elaborato con successo restituisce HTTP 200 con array accepted e rejected:
{
"accepted": [
{ "external_id": "crm-listing-00123", "import_item_id": "uuid-…" }
],
"rejected": []
}Struttura della richiesta
Il corpo di livello superiore è { listings: [...] }. Campi obbligatori per ciascun annuncio:
| Campo | Obbligatorio? | Note |
|---|---|---|
| external_id | Obbligatorio | Your CRM’s unique ID. Used for idempotent re-imports and deduplication. |
| listing_type | Obbligatorio | SELL o RENT. |
| real_estate_type | Obbligatorio | APARTMENT, HOUSE, LAND, COMMERCIAL o OTHER. |
| price | Obbligatorio | Numerico. Utilizzi il campo currency per il codice ISO 4217 (predefinito EUR). |
| address OR coordinates | Obbligatorio | Fornisca un oggetto address (street, city, country_code) oppure le coordinate ({ lat, lng }). Almeno uno dei due deve essere presente. |
| currency | Opzionale | Codice ISO 4217, ad es. EUR, CZK, PLN. Predefinito EUR. |
| name, description | Opzionale | Titolo dell'annuncio e descrizione in testo libero. |
| floorage, floor, rooms | Opzionale | Superficie dell'immobile in m², numero del piano e numero di stanze. |
| images | Opzionale | Array di URL pubblici di immagini. Il worker di importazione le scarica e le memorizza nella cache. |
| contact | Opzionale | Nome dell'agente, email e telefono per l'instradamento delle richieste. |
Vedi lo schema completo con tutti i campi facoltativi nella riferimento API interattivo.
Struttura della risposta ed errori
L'endpoint /v1/listings restituisce sempre HTTP 200 OK purché la richiesta stessa sia ben formata (JSON valido, header di autenticazione corretto, entro i limiti di dimensione). Gli errori dei singoli annunci sono riportati all'interno dell'array rejected — non come codici di errore HTTP.
Ogni elemento rifiutato include external_id, error_code e un messaggio leggibile. Gli errori a livello di batch (autenticazione errata, payload sovradimensionato) restituiscono uno stato HTTP diverso da 200 con un error_code di livello superiore.
Codici di errore
I codici a livello di batch restituiscono errori HTTP. I codici per singolo elemento appaiono nell'array rejected di una risposta 200.
| error_code | HTTP / ambito | Significato |
|---|---|---|
| MISSING_AUTHORIZATION | 401 | Nessuna intestazione Authorization inviata. |
| INVALID_KEY | 401 | La chiave non è stata trovata, è stata revocata o è scaduta. |
| SUBSCRIPTION_INACTIVE | 403 | The agency’s subscription is not active or past_due. |
| PAYLOAD_TOO_LARGE | 413 | Il corpo della richiesta supera il limite di 25 MB. |
| TOO_MANY_ITEMS | 413 | L'array listings contiene più di 5.000 elementi. |
| VALIDATION_FAILED | per elemento | Uno o più campi obbligatori sono mancanti o contengono un valore non valido. Controlli il campo message per i dettagli. |
| GEOCODE_ADDRESS_NOT_FOUND | per elemento | L'indirizzo fornito non è stato risolto in coordinate. Verifichi street, city e country_code. |
| GEOCODE_COORDINATES_INVALID | per elemento | I valori lat/lng forniti sono fuori dagli intervalli validi (lat ±90, lng ±180). |
| INFRA_QUEUE_REJECTED | per elemento | La coda del workflow ha rifiutato l'elemento, generalmente per un sovraccarico temporaneo. Riprovi dopo un breve ritardo. |
| INFRA_LOST | per elemento | Il workflow è stato accettato ma il suo risultato non è mai stato registrato. Utilizzi l'endpoint di retry. |
| INTERNAL_ERROR | per elemento | Si è verificato un errore imprevisto del server. Un nuovo tentativo potrebbe avere successo; contatti l'assistenza se il problema persiste. |
Idempotenza / reimportazioni
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.
Internamente, ogni elemento importato è associato a un Cloudflare Workflow con l'ID:
agency-{agency_id}-{external_id}Scadenza degli annunci
Ogni annuncio importato ha un TTL di 60 giorni dall'ultima importazione riuscita. Allo scadere del TTL, l'annuncio viene automaticamente rimosso dalla pubblicazione da un cron job giornaliero.
Per mantenere un annuncio attivo a tempo indeterminato, lo reimporti (anche con dati identici) prima della scadenza dei 60 giorni. Si consiglia di implementare una sincronizzazione notturna degli annunci attivi.
Stato + ritentativo
Utilizzi GET /v1/import-items/{import_item_id}/status per interrogare lo stato di elaborazione di un singolo elemento. L'import_item_id viene restituito nell'array accepted della risposta POST originale.
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"
}Se un elemento finisce in stato INFRA_LOST o INFRA_QUEUE_REJECTED, lo rimetta in coda senza inviare nuovamente l'intero batch:
curl -X POST https://ingest.seeki.eu/v1/import-items/{import_item_id}/retry \
-H "Authorization: Bearer seeki_live_your_key_here"Limiti
- Dimensione del corpo: 25 MB massimo per richiesta.
- Elementi per richiesta: 5.000 massimo. Suddivida i batch più grandi.
- Attualmente non è applicato alcun limite QPS. Picchi molto elevati possono essere limitati automaticamente; distribuisca le sincronizzazioni ad alto volume su più richieste.
OpenImmo XML / zip intake
OpenImmo is the de-facto real-estate exchange format for the DACH market (Germany, Austria, Switzerland) and is produced by every major CRM in those countries — FlowFact, onOffice, ImmoMaster, edomi, and others. If your CRM already exports OpenImmo, you can POST it directly without remapping fields into Seeki-JSON.
Two delivery flavours are accepted on the same endpoint, distinguished byContent-Type:
application/xml— raw OpenImmo XML, images referenced by absolute URL.application/zip— bundle containingindex.xmlat the root plus the JPGs referenced from<anhang gruppe="INTERN">nodes. We extract every referenced image, host it on Supabase Storage, and rewrite the listing’smedia.imagesarray before publication. Hosted images are removed when the listing expires (60-day default TTL); re-imports refresh them.
curl -X POST https://ingest.seeki.eu/v1/openimmo \
-H "Authorization: Bearer seeki_live_your_key_here" \
-H "Content-Type: application/xml" \
--data-binary @export.xmlcurl -X POST https://ingest.seeki.eu/v1/openimmo \
-H "Authorization: Bearer seeki_live_your_key_here" \
-H "Content-Type: application/zip" \
--data-binary @export.zipTarget spec version: OpenImmo 1.2.x. Body cap: 200 MB. Bigger feeds get a 413 with a Suggested-Chunk-Size: 500 header — split index.xml into multiple POSTs of ≤500 listings each. Spec reference: openimmo.de.
The same per-item error codes from the JSON intake apply — only the request body format differs. Each <immobilie> that fails Zod validation appears in the response’s rejected array with a VALIDATION_FAILED code and the offending field path.
Idealista XML-ML intake
Idealista’s XML-ML (xmlGenerator) is the standard feed format on the Iberian peninsula — used by Idealista itself and the CRMs that export to it for the Spanish (ES) and Portuguese (PT) markets. Country is inferred per record from the <provincia> field; locale follows country.
Images are referenced by URL (<imagenes><imagen url="…"/>), so there is no zip flavour for this format — application/xml only. Listings without an accessible image URL are still accepted; only fields that fail Zod validation are rejected.
curl -X POST https://ingest.seeki.eu/v1/idealista \
-H "Authorization: Bearer seeki_live_your_key_here" \
-H "Content-Type: application/xml" \
--data-binary @feed.xmlTarget spec: Idealista xmlGenerator-1.X. The XML prolog encoding declaration is honoured — feeds shipped as windows-1252 are decoded correctly without manual conversion. Body cap: 200 MB. Spec reference: search Idealista’s help centre for “XML feed schema”.
Same per-item error codes as the JSON intake — see the table above.
Passaggio in produzione
Esistono due ambienti separati. Le chiavi API hanno ambito limitato all'ambiente — una chiave di produzione non funzionerà in staging, e viceversa.
| Ambiente | URL base |
|---|---|
| Staging | https://ingest.seeki.store/v1 |
| Produzione | https://ingest.seeki.eu/v1 |
Tutti gli endpoint (/listings, /import-items/{id}/status, /import-items/{id}/retry) sono identici in entrambi gli ambienti.
Pronto a integrare?
Apra il riferimento interattivo per esplorare tutti i campi, provare le richieste nel browser e scaricare lo Schema JSON per il suo validatore.