Verifica le schede di un'attività con un listings scan
Controlla un'attività su mappe, motori di ricerca, directory e assistenti AI, nome, indirizzo e telefono per directory; risultati via webhook o polling.
Un listings scan verifica come un'attività è presente nella rete di directory di listingsAPI e indica, per ogni directory, se viene trovata e se nome, indirizzo e numero di telefono corrispondono ai dati forniti. L'attività non deve necessariamente essere una sede nel tuo account. Questa guida crea una scansione, attende che termini e legge i risultati.
Usalo per:
- verificare un potenziale cliente prima di acquisirlo, in modo che il primo confronto parta dalle schede mancanti o errate;
- controllare la presenza di un cliente e la coerenza dei dati NAP (nome, indirizzo, numero di telefono) prima e dopo aver corretto le sue schede;
- consentire a un agente AI di rispondere alla domanda "come è presente questa attività nelle directory?" senza aggiungere l'attività all'account.
1. Crea la scansione
POST /listings/scans accetta i dati dell'attività come un unico oggetto input e restituisce immediatamente la scansione nello stato QUEUED. Le directory vengono controllate in background.
curl -X POST https://listingsapi.com/api/v4/listings/scans \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d @- <<'JSON'{"input": { "name": "Joe's Pizza", "street": "7 Carmine Street", "city": "New York", "stateIso": "NY", "postalCode": "10014", "countryIso": "US", "phone": "2123661182"}}JSONLa risposta restituisce la scansione, con phone normalizzato nel formato internazionale. results è vuoto finché non vengono controllate le directory, quindi conserva id.
{ "data": { "createListingScan": { "reused": false, "scan": { "id": "TGlzdGluZ1NjYW46Mzk0YTRhNWMtZjcwMy00NjZiLTg2NjAtMDU4MTlmNDhkZjMz", "status": "QUEUED", "source": "DIRECTORY_SEARCH", "locationId": null, "resultsAsOf": null, "createdAt": "2026-11-05T07:01:08Z", "startedAt": null, "completedAt": null, "business": { "name": "Joe's Pizza", "street": "7 Carmine Street", "city": "New York", "stateIso": "NY", "postalCode": "10014", "countryIso": "US", "phone": "+12123661182" }, "summary": { "total": 0, "found": 0, "accurate": 0, "inaccurate": 0, "notFound": 0, "pending": 0, "unavailable": 0 }, "failure": null, "results": [] }, "errors": [] } }}La risposta include anche un oggetto quota, descritto in Costi, limiti ed errori.
2 aspetti da controllare prima di proseguire:
reused. Quando invii una richiesta per un'attività che hai sottoposto a scansione negli ultimi 7 giorni, listingsAPI restituisce quella scansione invece di avviarne una nuova, conreused: truee il suo stato attuale, di solitoCOMPLETED. La tua quota non viene consumata e non viene inviato un nuovo webhook per quella scansione.errors. Anche una richiesta rifiutata riceve una risposta con stato HTTP200. Il rifiuto è indicato indata.createListingScan.errorsescanènull. Un numero di telefono troppo corto produce questo risultato:
{ "data": { "createListingScan": { "reused": false, "scan": null, "errors": [ { "code": "SY83003", "message": "SY83003: Invalid value for phone", "contextInfo": [ { "key": "field", "value": "phone" } ] } ] } }}contextInfo indica il nome del campo che non ha superato la convalida. Gli altri codici che puoi ricevere sono riportati nella tabella degli errori.
2. Attendi i risultati
Una scansione passa da QUEUED a IN_PROGRESS, poi a COMPLETED o FAILED. La maggior parte termina in un intervallo compreso tra 1 e 7 minuti. Se una directory non ha risposto dopo circa 15 minuti, il suo risultato viene impostato su UNAVAILABLE e la scansione termina con gli altri risultati. Usa un webhook se puoi e ricorri al polling solo come alternativa.
2a. Ricevi il webhook (consigliato)
Quando la scansione raggiunge uno stato finale, listingsAPI invia un evento listing_scan.completed o listing_scan.failed all'URL del tuo webhook. Il suo data.scan è lo stesso oggetto restituito da GET, risultati inclusi, quindi non devi recuperare altri dati in seguito.
{ "event": "listing_scan.completed", "timestamp": "2026-11-05T07:01:52Z", "account_id": 12345, "data": { "scan": { "id": "TGlzdGluZ1NjYW46Mzk0YTRhNWMtZjcwMy00NjZiLTg2NjAtMDU4MTlmNDhkZjMz", "status": "COMPLETED", "summary": { "total": 62, "found": 21, "accurate": 18, "inaccurate": 2, "notFound": 41, "pending": 0, "unavailable": 0 }, "results": [ "..." ] } }}Il payload è abbreviato qui; l'esempio completo si trova nella documentazione di riferimento degli eventi. Gli eventi vengono firmati e consegnati come tutti gli altri eventi, con 1 tentativo e un tempo massimo di 5 secondi, quindi verifica la firma, memorizza il corpo originale e conferma la ricezione prima di fare qualsiasi altra cosa. Il ricevitore descritto in Reagire agli eventi con i webhook esegue già queste operazioni; l'unica modifica consiste nell'aggiungere un ramo condizionale basato su event.
# After the signature check and the endpoint.verification branch:if body.get("event") in ("listing_scan.completed", "listing_scan.failed"): inbox.put(raw) # commit before the 200; read data.scan from the queue return {"received": True}, 200Un evento viene inviato solo agli account con webhook abilitati e un URL verificato. Se il tuo account non soddisfa queste condizioni, o se un evento non arriva, esegui il polling della scansione; in entrambi i casi, la scansione viene conservata per 90 giorni. I dettagli sulla firma si trovano in Firme e verifica.
2b. Usa il polling come alternativa
GET /listings/scans/{scanId} restituisce la scansione con tutti i risultati disponibili fino a quel momento. Durante la scansione, results si popola man mano che le directory rispondono e summary.pending conta quelle ancora in attesa di risposta. Esegui il polling ogni 15 secondi, non più spesso; ogni richiesta viene conteggiata ai fini del tuo limite di frequenza.
SCAN_ID="TGlzdGluZ1NjYW46Mzk0YTRhNWMtZjcwMy00NjZiLTg2NjAtMDU4MTlmNDhkZjMz" while true; doscan=$(curl -s "https://listingsapi.com/api/v4/listings/scans/$SCAN_ID" \ -H "Authorization: API $LISTINGSAPI_KEY")status=$(echo "$scan" | jq -r '.data.listingScan.status')echo "status: $status"case "$status" in COMPLETED|FAILED) echo "$scan" | jq '.data.listingScan | {status, summary, failure}' break ;; null) echo "$scan" break ;;esacsleep 15doneUna scansione i cui risultati provengono da una scansione recente o da una delle tue sedi è nello stato COMPLETED fin dalla creazione, quindi basta una sola richiesta GET.
3. Leggi i risultati
Una scansione completata contiene un summary e una voce in results per ogni directory verificata, fino a circa 60 a seconda del paese. business restituisce i dati che hai inviato, con phone normalizzato nel formato internazionale.
{ "total": 62, "found": 21, "accurate": 18, "inaccurate": 2, "notFound": 41, "pending": 0, "unavailable": 0}total è il numero di directory. found indica quante contengono una scheda dell'attività e si suddivide in accurate, inaccurate ed eventuali schede che confermano solo la presenza, descritte di seguito. notFound indica quante non contengono una scheda dell'attività. unavailable conta le directory che non è stato possibile verificare questa volta, mentre pending è diverso da zero solo durante la scansione.
Ogni risultato contiene un status per la directory:
Per un risultato FOUND, accurate indica se la scheda corrisponde ai dati che hai inviato:
truesignifica che nome, indirizzo e numero di telefono corrispondono tutti.falsesignifica che almeno uno non corrisponde. Un campo omesso dalla scheda viene considerato non corrispondente, quindi una scheda senza numero di telefono èfalse.nullsignifica che l'attività è stata trovata, ma non è stata eseguita una verifica campo per campo.
accuracy spiega l'esito con un status e un message per ciascuno dei campi name, address e phone. Il valore di status è ACCURATE, INACCURATE o MISSING, mentre message è null quando il campo è corretto. Ecco una pagina Facebook in cui nome e indirizzo corrispondono, ma manca il numero di telefono:
{ "directory": { "id": 184, "name": "Facebook", "url": "facebook.com" }, "status": "FOUND", "accurate": false, "accuracySource": "DIRECTORY_MATCH", "accuracy": { "name": { "status": "ACCURATE", "message": null }, "address": { "status": "ACCURATE", "message": null }, "phone": { "status": "MISSING", "message": "No phone number on the listing" } }, "listing": { "name": "Joe's Pizza", "street": "7 Carmine St", "city": "New York", "state": "NY", "postalCode": "10014", "country": "US", "fullAddress": "7 Carmine St, New York, NY 10014", "phones": [], "url": "https://www.facebook.com/177353602413952" }, "syncStatus": null}Alcune directory confermano solo che l'attività esiste e non mostrano dettagli sufficienti per un confronto. Per queste directory viene restituito FOUND con accurate: null e i risultati vengono conteggiati solo in found, non in accurate o inaccurate. Considera queste schede presenti, ma non verificate:
{ "directory": { "id": 374, "name": "Map Quest", "url": "www.mapquest.com" }, "status": "FOUND", "accurate": null, "accuracySource": "DIRECTORY_MATCH", "accuracy": { "name": { "status": "ACCURATE", "message": null }, "address": { "status": "MISSING", "message": "Not shown" }, "phone": { "status": "MISSING", "message": "Not shown" } }, "listing": { "name": "Joe's Pizza", "street": "7 Carmine St", "city": "New York", "state": "NY", "postalCode": "10014", "country": null, "fullAddress": "7 Carmine St, New York, NY 10014, US", "phones": [], "url": null }, "syncStatus": null}Un risultato NOT_FOUND non contiene né listing né accuracy:
{ "directory": { "id": 352, "name": "YellowPages", "url": "www.yellowpages.com" }, "status": "NOT_FOUND", "accurate": null, "accuracySource": "DIRECTORY_MATCH", "accuracy": null, "listing": null, "syncStatus": null}Diverse directory non dispongono di dati propri. Uber, Waze e Lyft mostrano i dati di Google Maps, mentre Copilot mostra quelli di Bing. I loro risultati rispecchiano la directory di origine, quindi di solito ripetono quanto restituito da Google Maps o Bing e non contengono un url della scheda. Conteggiali come voci separate in summary, ma non considerarli conferme indipendenti:
{ "directory": { "id": 350, "name": "Uber", "url": "uber.com" }, "status": "FOUND", "accurate": true, "accuracySource": "DIRECTORY_MATCH", "accuracy": { "name": { "status": "ACCURATE", "message": null }, "address": { "status": "ACCURATE", "message": null }, "phone": { "status": "ACCURATE", "message": null } }, "listing": { "name": "Joe's Pizza", "street": "7 Carmine Street", "city": "New York", "state": "NY", "postalCode": "10014", "country": "US", "fullAddress": "7 Carmine St, New York, NY 10014, USA", "phones": [ "+1 212-366-1182" ], "url": null }, "syncStatus": null}Sono inclusi anche gli assistenti di IA come ChatGPT e Gemini. Per questi, listing mostra ciò che l'assistente sa dell'attività, spesso solo un nome, un indirizzo completo e un numero di telefono, e non è presente un accuracy per ogni campo.
Per trasformare una scansione completata in un elenco di correzioni, stampa ogni directory con un campo errato o mancante:
curl -s https://listingsapi.com/api/v4/listings/scans/TGlzdGluZ1NjYW46Mzk0YTRhNWMtZjcwMy00NjZiLTg2NjAtMDU4MTlmNDhkZjMz \-H "Authorization: API $LISTINGSAPI_KEY" \| jq -r '.data.listingScan.results[] | select(.accurate == false) | .directory.name as $directory | .accuracy | to_entries[] | select(.value.status != "ACCURATE") | $directory + " " + .key + ": " + (.value.message // .value.status)'Per la scansione di Joe's Pizza vengono stampate due righe: su Facebook manca il numero di telefono e Judys Book ne mostra uno diverso.
Facebook phone: No phone number on the listingJudys Book phone: Phone number does not matchDa dove provengono i risultati
source indica come sono stati ottenuti i risultati della scansione e resultsAsOf indica quando sono stati raccolti i dati.
Costi, limiti ed errori
Solo una nuova scansione DIRECTORY_SEARCH consuma la quota mensile, che dipende dal tuo piano e si rinnova a ogni periodo di fatturazione. Queste operazioni sono gratuite:
- ripetere una scansione della stessa attività entro 7 giorni. Viene restituita la tua scansione precedente con
reused: true; - una scansione i cui risultati possono essere ricavati da una scansione recente della stessa attività eseguita da qualsiasi account. È una copia
RECENT_SCAN; - scansioni che corrispondono a una delle tue sedi (
LOCATION_LISTINGS); - scansioni che terminano con
FAILED, per le quali viene rimborsata la quota consumata.
Le scansioni vengono conservate per 90 giorni. Trascorso questo periodo, GET restituisce 404 con SY83005.
Le risposte di create e list includono un oggetto quota, così puoi verificare la quota disponibile prima di avviare un gruppo di scansioni. List restituisce le tue scansioni dalla più recente alla meno recente, in pagine da 1 a 50 elementi con perPage, senza results.
curl -s "https://listingsapi.com/api/v4/listings/scans?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.listingScans.quota'Questi sono gli errori che incontrerai più spesso. Create restituisce gli errori nel corpo della risposta con stato HTTP 200; get e list restituiscono il consueto stato HTTP.
Una richiesta GET per un id che non esiste restituisce:
{ "data": { "listingScan": null }, "errors": [ { "message": "SY83005: Listing scan not found" } ]}Una scansione che termina con FAILED riporta il motivo in failure e results rimane vuoto:
{ "status": "FAILED", "failure": { "code": "SY83010", "message": "SY83010: Listing scans are temporarily unavailable, try again later", "field": null }}Il formato generale degli errori è descritto in Codici di errore.
Per gli agenti IA
Il server MCP ospitato espone questa funzionalità tramite 3 strumenti: listings_scans_create, listings_scans_get e listings_scans_list. Un assistente può avviare una scansione per un'attività indicata dall'utente, verificarne periodicamente lo stato con listings_scans_get e riepilogare le directory che richiedono attenzione. Come per REST, la creazione di una scansione richiede una chiave Write. La configurazione è descritta in Collega gli agenti IA a MCP di listingsAPI.
Passaggi successivi
- Reagisci agli eventi con i webhook: il ricevitore a cui arrivano gli eventi delle scansioni.
- Controlla lo stato delle schede e i link alle schede pubblicate e Trova e correggi gli errori delle schede: una volta che un'attività è una sede nel tuo account, monitora e correggi le sue schede.
- Aggiungi una sede: aggiungi al tuo account l'attività che hai verificato.
- Riferimenti: Crea una listings scan, Recupera una listings scan, Elenca le listings scans, Riferimento degli eventi, Codici di errore.