Audita las fichas de un negocio con un listings scan
Revisa un negocio en mapas, buscadores, directorios y asistentes de IA, la precisión de sus datos por directorio y recibe resultados por webhook o polling.
Un listings scan comprueba cómo aparece un negocio en la red de directorios de listingsAPI y te indica, directorio por directorio, si se encuentra y si su nombre, dirección y teléfono coinciden con los que proporcionaste. El negocio no tiene que ser una ubicación de tu cuenta. Esta guía crea un escaneo, espera a que termine y lee los resultados.
Úsalo para:
- auditar a un posible cliente antes de incorporarlo, para que la primera conversación empiece por las fichas que faltan o contienen errores;
- comprobar la presencia de un cliente y la coherencia de sus datos NAP (nombre, dirección y teléfono) antes y después de corregir sus fichas;
- dar a un agente de IA una forma de responder a «¿cómo aparece este negocio en los directorios?» sin añadir el negocio a la cuenta.
1. Crea el escaneo
POST /listings/scans recibe los datos del negocio en un único objeto input y devuelve de inmediato el escaneo en estado QUEUED. Los directorios se comprueban en segundo plano.
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 respuesta devuelve el escaneo, con phone normalizado al formato internacional. results está vacío hasta que se comprueban los directorios, así que 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 respuesta también incluye un objeto quota, que se explica en Costes, límites y errores.
Comprueba estas 2 cosas antes de continuar:
reused. Cuando solicitas un escaneo de un negocio que ya escaneaste en los últimos 7 días, listingsAPI devuelve ese escaneo en lugar de iniciar uno nuevo, conreused: truey su estado actual, normalmenteCOMPLETED. No se descuenta nada de tu cuota ni se envía un nuevo webhook para ese escaneo.errors. Una solicitud rechazada también recibe el estado HTTP200. El rechazo se indica endata.createListingScan.errors, yscanesnull. Un número de teléfono demasiado corto produce este resultado:
{ "data": { "createListingScan": { "reused": false, "scan": null, "errors": [ { "code": "SY83003", "message": "SY83003: Invalid value for phone", "contextInfo": [ { "key": "field", "value": "phone" } ] } ] } }}contextInfo indica el nombre del campo que falló. Los demás códigos que puedes recibir se encuentran en la tabla de errores.
2. Espera los resultados
Un escaneo pasa de QUEUED a IN_PROGRESS y después a COMPLETED o FAILED. La mayoría termina en un plazo de entre 1 y 7 minutos. Si un directorio no ha respondido al cabo de unos 15 minutos, su resultado se establece en UNAVAILABLE y el escaneo se completa con los demás resultados. Usa un webhook si puedes y recurre a las consultas periódicas solo como alternativa.
2a. Recibe el webhook (recomendado)
Cuando el escaneo alcanza un estado final, listingsAPI envía un único evento listing_scan.completed o listing_scan.failed a tu URL de webhook. Su data.scan es el mismo objeto que devuelve GET, con los resultados incluidos, así que no tienes que obtener nada más después.
{ "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": [ "..." ] } }}Aquí se muestra una versión abreviada del cuerpo del evento; el ejemplo completo está en la referencia de eventos. Los eventos se firman y se entregan como cualquier otro evento, con 1 intento y un tiempo máximo de 5 segundos, así que verifica la firma, guarda el cuerpo sin procesar y confirma la recepción antes de hacer cualquier otra cosa. El receptor de Reaccionar a eventos con webhooks ya hace esto; el único cambio es añadir una rama más según 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 solo se envía a las cuentas que tienen los webhooks habilitados y una URL verificada. Si tu cuenta no cumple estas condiciones, o si un evento nunca llega, consulta periódicamente el escaneo; el escaneo se conserva durante 90 días en cualquier caso. Los detalles de la firma están en Firmas y verificación.
2b. Consulta periódicamente como alternativa
GET /listings/scans/{scanId} devuelve el escaneo con los resultados disponibles hasta ese momento. Mientras se ejecuta el escaneo, results se completa a medida que responden los directorios y summary.pending cuenta los que siguen pendientes. Consulta cada 15 segundos y no con mayor frecuencia; cada solicitud cuenta para tu límite de solicitudes.
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 15doneUn escaneo cuyos resultados proceden de un escaneo reciente o de una de tus propias ubicaciones tiene el estado COMPLETED desde el momento en que se crea, por lo que basta con una sola solicitud GET.
3. Lee los resultados
Un escaneo completado tiene un summary y una entrada en results por cada directorio comprobado, hasta unos 60 según el país. business devuelve los datos que enviaste, con phone normalizado al formato internacional.
{ "total": 62, "found": 21, "accurate": 18, "inaccurate": 2, "notFound": 41, "pending": 0, "unavailable": 0}total es el número de directorios. found indica cuántos tienen una ficha del negocio y se desglosa en accurate, inaccurate y las fichas que solo confirman la presencia descritas a continuación. notFound indica cuántos no tienen una ficha del negocio. unavailable cuenta los directorios que no se pudieron comprobar en esta ocasión, y pending solo es distinto de cero mientras se ejecuta el escaneo.
Cada resultado tiene un status correspondiente al directorio:
Para un resultado FOUND, accurate indica si la ficha coincide con los datos que enviaste:
truesignifica que el nombre, la dirección y el teléfono coinciden.falsesignifica que al menos uno no coincide. Un campo que la ficha omite se considera una discrepancia, por lo que una ficha sin número de teléfono esfalse.nullsignifica que se encontró el negocio, pero no se realizó una comprobación campo por campo.
accuracy explica la evaluación con un status y un message para cada uno de los campos name, address y phone. El valor de status es ACCURATE, INACCURATE o MISSING, y message es null cuando el campo es correcto. Esta página de Facebook coincide en el nombre y la dirección, pero no tiene número de teléfono:
{ "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}Algunos directorios solo confirman que el negocio existe y no muestran suficientes detalles para comparar. Estos resultados se devuelven como FOUND con accurate: null y se cuentan únicamente en found, no en accurate ni en inaccurate. Trátalos como presentes, no como verificados:
{ "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 resultado NOT_FOUND no tiene listing ni accuracy:
{ "directory": { "id": 352, "name": "YellowPages", "url": "www.yellowpages.com" }, "status": "NOT_FOUND", "accurate": null, "accuracySource": "DIRECTORY_MATCH", "accuracy": null, "listing": null, "syncStatus": null}Varios directorios no almacenan datos propios. Uber, Waze y Lyft muestran datos de Google Maps, y Copilot muestra datos de Bing. Sus resultados reflejan los del directorio de origen, por lo que suelen repetir lo que devolvieron Google Maps o Bing, y no tienen un url de la ficha. Cuéntalos como entradas separadas en summary, pero no los interpretes como una confirmación independiente:
{ "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}También se incluyen asistentes de IA como ChatGPT y Gemini. En su caso, listing muestra lo que el asistente sabe sobre el negocio, que a menudo se limita a un nombre, una dirección completa y un número de teléfono, y no hay un accuracy por campo.
Para convertir un escaneo completado en una lista de correcciones, imprime cada directorio que tenga un campo incorrecto o ausente:
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)'Para el escaneo de Joe's Pizza, esto imprime dos líneas: Facebook no tiene número de teléfono y Judys Book muestra uno diferente.
Facebook phone: No phone number on the listingJudys Book phone: Phone number does not matchDe dónde proceden los resultados
source indica cómo se obtuvieron los resultados del escaneo, y resultsAsOf indica cuándo se recopilaron los datos.
Costes, límites y errores
Solo un nuevo escaneo DIRECTORY_SEARCH consume tu cuota mensual, que depende de tu plan y se restablece con tu periodo de facturación. Los siguientes casos son gratuitos:
- repetir un escaneo del mismo negocio en un plazo de 7 días. Se devuelve tu propio escaneo anterior con
reused: true; - un escaneo cuyos resultados pueden obtenerse de un escaneo reciente del mismo negocio realizado desde cualquier cuenta. Es una copia
RECENT_SCAN; - los escaneos que coinciden con una de tus propias ubicaciones (
LOCATION_LISTINGS); - los escaneos que terminan en
FAILED, cuyo consumo se reembolsa.
Los escaneos se conservan durante 90 días. Después de ese plazo, GET devuelve 404 con SY83005.
Las respuestas de creación y listado incluyen un objeto quota para que puedas consultar tu consumo antes de iniciar un lote. La operación de listado devuelve tus escaneos del más reciente al más antiguo, en páginas de 1 a 50 con perPage, sin results.
curl -s "https://listingsapi.com/api/v4/listings/scans?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.listingScans.quota'Estos son los errores que verás con más frecuencia. La operación de creación devuelve sus errores en el cuerpo con HTTP 200; las operaciones de obtención y listado devuelven el estado HTTP habitual.
Una solicitud GET para un id que no existe devuelve:
{ "data": { "listingScan": null }, "errors": [ { "message": "SY83005: Listing scan not found" } ]}Un escaneo que termina en FAILED tiene el motivo en failure, y results permanece vacío:
{ "status": "FAILED", "failure": { "code": "SY83010", "message": "SY83010: Listing scans are temporarily unavailable, try again later", "field": null }}El formato general de los errores se describe en Códigos de error.
Para agentes de IA
El servidor MCP alojado ofrece esta función mediante tres herramientas: listings_scans_create, listings_scans_get y listings_scans_list. Un asistente puede iniciar un escaneo de un negocio que indique el usuario, consultar periódicamente su estado con listings_scans_get y resumir los directorios que requieren atención. Al igual que con REST, crear un escaneo requiere una clave Write. La configuración se describe en Conecta agentes de IA al MCP de listingsAPI.
Siguientes pasos
- Reacciona a eventos con webhooks: el receptor al que llegan los eventos del escaneo.
- Comprueba el estado de las fichas y sus enlaces públicos y Busca y corrige errores en las fichas: una vez que un negocio sea una ubicación en tu cuenta, supervisa y corrige sus fichas.
- Añade una ubicación: incorpora el negocio que auditaste.
- Referencia: Crea un listings scan, Obtén un listings scan, Lista los listings scans, Referencia de eventos, Códigos de error.