تدقيق إدراجات نشاط تجاري باستخدام listings scan
افحص ظهور أي نشاط تجاري في الخرائط ومحركات البحث والأدلة ومساعدي الذكاء الاصطناعي، ودقة اسمه وعنوانه وهاتفه لكل دليل، وتلقّ النتائج عبر webhook أو polling.
تتحقق عملية listings scan من كيفية إدراج نشاط تجاري واحد عبر شبكة الأدلة listingsAPI، وتوضح لك، لكل دليل على حدة، ما إذا كان النشاط التجاري موجودًا فيه وما إذا كان اسمه وعنوانه ورقم هاتفه تطابق البيانات التي قدمتها. لا يلزم أن يكون النشاط التجاري موقعًا في حسابك. يوضح هذا الدليل كيفية إنشاء فحص، وانتظار اكتماله، وقراءة النتائج.
استخدمه من أجل:
- تدقيق إدراجات نشاط تجاري لعميل محتمل قبل ضمه، لتبدأ المحادثة الأولى بالإدراجات المفقودة أو غير الصحيحة؛
- التحقق من وجود نشاط العميل التجاري واتساق بيانات NAP (الاسم والعنوان ورقم الهاتف) قبل إصلاح إدراجات نشاطه التجاري وبعده؛
- تمكين وكيل ذكاء اصطناعي من الإجابة عن السؤال «كيف يُدرج هذا النشاط التجاري؟» دون إضافة النشاط التجاري إلى الحساب.
1. إنشاء الفحص
يستقبل POST /listings/scans بيانات النشاط التجاري في كائن input واحد، ويُعيد الفحص فورًا بالحالة QUEUED. يجري التحقق من الأدلة في الخلفية.
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"}}JSONتُعيد الاستجابة الفحص، مع توحيد صيغة phone إلى الصيغة الدولية. يظل results فارغًا إلى أن يجري التحقق من الأدلة، لذا احتفظ بـ 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": [] } }}تتضمن الاستجابة أيضًا كائن quota، الموضح في التكاليف والحدود والأخطاء.
تحقق من أمرين قبل المتابعة:
reused. عندما تطلب فحص نشاط تجاري فحصته خلال آخر 7 أيام، يُعيد listingsAPI ذلك الفحص بدلًا من بدء فحص جديد، معreused: trueوحالته الحالية، التي تكون عادةًCOMPLETED. لا يُخصم شيء من حصتك، ولا يُرسل webhook جديد لهذا الفحص.errors. يُعاد رمز HTTP200حتى عند رفض الطلب. يرد الرفض فيdata.createListingScan.errors، وتكون قيمةscanهيnull. يبدو الرد على رقم هاتف أقصر من الحد المطلوب كما يلي:
{ "data": { "createListingScan": { "reused": false, "scan": null, "errors": [ { "code": "SY83003", "message": "SY83003: Invalid value for phone", "contextInfo": [ { "key": "field", "value": "phone" } ] } ] } }}يحدد contextInfo اسم الحقل الذي فشل التحقق منه. ترد الرموز الأخرى التي قد تتلقاها في جدول الأخطاء.
2. انتظار النتائج
ينتقل الفحص من QUEUED إلى IN_PROGRESS ثم إلى COMPLETED أو FAILED. تكتمل معظم الفحوص خلال 1 إلى 7 دقائق. إذا لم يستجب دليل بعد نحو 15 دقيقة، تُضبط نتيجته على UNAVAILABLE ويكتمل الفحص بالنتائج الأخرى. استخدم webhook إن أمكن، واجعل الاستعلام الدوري خيارًا احتياطيًا فقط.
2a. استقبال webhook (موصى به)
عندما يصل الفحص إلى حالة نهائية، يرسل listingsAPI حدثًا واحدًا من نوع listing_scan.completed أو listing_scan.failed إلى عنوان URL الخاص بـ webhook لديك. يحتوي data.scan فيه على الكائن نفسه الذي يُعيده GET، بما في ذلك النتائج، لذا لا يلزم جلب أي شيء بعد ذلك.
{ "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": [ "..." ] } }}محتوى الطلب مختصر هنا؛ والمثال الكامل متاح في مرجع الأحداث. تُوقَّع الأحداث وتُسلَّم مثل سائر الأحداث، بمحاولة واحدة ومهلة 5 ثوانٍ، لذا تحقق من التوقيع، وخزّن جسم الطلب الخام، وأكّد الاستلام قبل القيام بأي شيء آخر. ينفذ المستقبِل الموضح في التعامل مع الأحداث باستخدام webhooks هذه الخطوات بالفعل؛ والتغيير الوحيد هو إضافة فرع آخر بناءً على 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}, 200لا يُرسل الحدث إلا إلى الحسابات التي فُعّلت فيها webhooks ولديها عنوان URL تم التحقق منه. إذا لم يستوفِ حسابك هذين الشرطين، أو إذا لم يصل حدث، فاستعلم عن الفحص دوريًا؛ إذ يُحتفظ بالفحص لمدة 90 يومًا في كلتا الحالتين. ترد تفاصيل التوقيع في التوقيعات والتحقق.
2b. الاستعلام الدوري كخيار بديل
يعيد GET /listings/scans/{scanId} الفحص مع أي نتائج متاحة حتى الآن. أثناء تشغيل الفحص، تُضاف البيانات إلى results مع ورود إجابات الأدلة، ويحسب summary.pending عدد الأدلة التي لا تزال إجاباتها قيد الانتظار. استعلم كل 15 ثانية، ولا تستعلم بوتيرة أسرع؛ يُحتسب كل طلب ضمن حد معدل الطلبات.
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 15doneيكون الفحص الذي تُستمد نتائجه من فحص حديث أو من أحد مواقعك بالحالة COMPLETED لحظة إنشائه، لذا يكفي إجراء GET مرة واحدة.
3. قراءة النتائج
يحتوي الفحص المكتمل على summary وسجل واحد في results لكل دليل تم التحقق منه، بحد أقصى يقارب 60 دليلاً حسب البلد. يعيد business المدخلات التي أرسلتها، مع توحيد تنسيق phone بالصيغة الدولية.
{ "total": 62, "found": 21, "accurate": 18, "inaccurate": 2, "notFound": 41, "pending": 0, "unavailable": 0}يمثل total عدد الأدلة. ويمثل found عدد الأدلة التي تدرج النشاط التجاري، وينقسم إلى accurate وinaccurate وأي إدراجات أنشطة تجارية تؤكد الوجود فقط كما هو موضح أدناه. ويمثل notFound عدد الأدلة التي لا تدرجه. يحسب unavailable عدد الأدلة التي تعذّر التحقق منها هذه المرة، ولا تكون قيمة pending غير صفرية إلا أثناء تشغيل الفحص.
تحتوي كل نتيجة على status للدليل:
بالنسبة إلى نتيجة FOUND، يوضح accurate ما إذا كان إدراج النشاط التجاري يطابق مدخلاتك:
- تعني
trueأن الاسم والعنوان ورقم الهاتف كلها متطابقة. - تعني
falseأن واحدًا منها على الأقل غير مطابق. يُحتسب الحقل غير الوارد في إدراج النشاط التجاري على أنه غير مطابق، لذا يكون إدراج النشاط التجاري الذي لا يتضمن رقم هاتف بالحالةfalse. - تعني
nullأنه تم العثور على النشاط التجاري، لكن لم يتم التحقق من كل حقل على حدة.
يوضح accuracy سبب النتيجة من خلال status وmessage لكل من name وaddress وphone. تكون قيمة status هي ACCURATE أو INACCURATE أو MISSING، وتكون قيمة message هي null عندما يكون الحقل صحيحًا. إليك صفحة Facebook يتطابق فيها الاسم والعنوان، لكنها لا تتضمن رقم هاتف:
{ "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}تؤكد بعض الأدلة وجود النشاط التجاري فقط، ولا تعرض تفاصيل كافية للمقارنة. تُعاد نتائج هذه الأدلة بالحالة FOUND مع accurate: null، وتُحتسب ضمن found فقط، وليس ضمن accurate أو inaccurate. تعامل معها على أنها موجودة، وليس على أنها متحقَّق من صحتها:
{ "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}لا تحتوي نتيجة NOT_FOUND على listing ولا على accuracy:
{ "directory": { "id": 352, "name": "YellowPages", "url": "www.yellowpages.com" }, "status": "NOT_FOUND", "accurate": null, "accuracySource": "DIRECTORY_MATCH", "accuracy": null, "listing": null, "syncStatus": null}لا تحتفظ عدة أدلة ببيانات خاصة بها. تعرض Uber وWaze وLyft بيانات Google Maps، ويعرض Copilot بيانات Bing. تعكس نتائجها نتائج الدليل المصدر، لذا فهي تكرر عادةً ما أعاده Google Maps أو Bing، ولا تتضمن url لإدراج النشاط التجاري. احتسبها كسجلات منفصلة في summary، لكن لا تعتبرها تأكيدًا مستقلاً:
{ "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}يشمل الفحص أيضًا مساعدي الذكاء الاصطناعي مثل ChatGPT وGemini. بالنسبة إليهم، يعرض listing ما يعرفه المساعد عن النشاط التجاري، وهو غالبًا مجرد اسم وعنوان كامل ورقم هاتف، ولا يوجد accuracy لكل حقل على حدة.
لتحويل فحص مكتمل إلى قائمة تصحيحات، اطبع كل دليل يحتوي على حقل خاطئ أو مفقود:
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)'بالنسبة إلى فحص Joe's Pizza، يطبع هذا سطرين: لا يتضمن Facebook رقم هاتف، ويعرض Judys Book رقمًا مختلفًا.
Facebook phone: No phone number on the listingJudys Book phone: Phone number does not matchمصادر النتائج
يوضح source كيفية الحصول على نتائج الفحص، ويشير resultsAsOf إلى وقت جمع البيانات.
التكاليف والحدود والأخطاء
لا يُحتسب من حصتك الشهرية إلا فحص DIRECTORY_SEARCH جديد، وتعتمد هذه الحصة على خطتك وتُعاد تهيئتها مع دورة الفوترة. الحالات التالية مجانية:
- تكرار فحص النشاط التجاري نفسه خلال سبعة أيام. يُعاد فحصك السابق مع
reused: true؛ - فحص يمكن الحصول على نتائجه من فحص حديث للنشاط التجاري نفسه أجراه أي حساب. يكون نسخة من نوع
RECENT_SCAN؛ - الفحوصات التي تطابق أحد مواقعك (
LOCATION_LISTINGS)؛ - الفحوصات التي تنتهي بحالة
FAILED، وتُعاد الحصة المحتسبة لها.
يُحتفظ بالفحوصات لمدة 90 يومًا. بعد ذلك، يُعيد GET القيمة 404 مع SY83005.
تتضمن استجابات الإنشاء والسرد كائن quota، لتتمكن من معرفة مقدار الحصة المتاح قبل بدء دفعة من الفحوصات. تُعيد عملية السرد فحوصاتك بدءًا من الأحدث، في صفحات تضم من 1 إلى 50 فحصًا مع perPage، دون results.
curl -s "https://listingsapi.com/api/v4/listings/scans?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.listingScans.quota'هذه هي الأخطاء التي ستصادفها غالبًا. تُعيد عملية الإنشاء أخطاءها في متن الاستجابة مع حالة HTTP 200؛ وتُعيد عمليتا الجلب والسرد حالة HTTP المعتادة.
يُعيد طلب GET لمعرّف غير موجود ما يلي:
{ "data": { "listingScan": null }, "errors": [ { "message": "SY83005: Listing scan not found" } ]}يحتوي failure على سبب انتهاء الفحص بحالة FAILED، ويظل results فارغًا:
{ "status": "FAILED", "failure": { "code": "SY83010", "message": "SY83010: Listing scans are temporarily unavailable, try again later", "field": null }}ترد الصيغة العامة للأخطاء في رموز الأخطاء.
لوكلاء الذكاء الاصطناعي
يتيح خادم MCP المستضاف هذه الميزة عبر ثلاث أدوات: listings_scans_create وlistings_scans_get وlistings_scans_list. يمكن للمساعد بدء فحص لنشاط تجاري يحدده المستخدم، والاستعلام دوريًا عن الفحص باستخدام listings_scans_get، وتلخيص الأدلة التي تحتاج إلى متابعة. كما في REST، يتطلب إنشاء فحص مفتاح Write. ترد تعليمات الإعداد في ربط وكلاء الذكاء الاصطناعي بخادم MCP الخاص بـ listingsAPI.
الخطوات التالية
- الاستجابة للأحداث باستخدام webhooks: المستقبِل الذي تصله أحداث الفحص.
- التحقق من حالة إدراج النشاط التجاري وروابطه المباشرة والعثور على أخطاء إدراج النشاط التجاري وإصلاحها: بعد إضافة النشاط التجاري كموقع في حسابك، تتبّع إدراجاته وأصلحها.
- إضافة موقع: أضف النشاط التجاري الذي دققت بياناته.
- المراجع: إنشاء listings scan، جلب listings scan، سرد listings scans، مرجع الأحداث، رموز الأخطاء.