المراجعات
كل نقاط نهاية التقييمات بأمثلة cURL وPython وNode: المصادر والإعدادات، القائمة، التجميع، التفاصيل، الرد، التعديل، الأرشفة، العبارات، التحليلات.
التقييمات هي التقييمات بالنجوم والتعليقات التي يتركها العملاء على Google وFacebook وYelp. تخزّن API نسخة واحدة من كل تقييم، وتتيح لك الرد عليه، وتحسب تحليلات التقييمات. تستخدم مسارات REST الاسم reviews؛ وتستخدم مفاتيح الاستجابة وعناوين الصفحات المرجعية الاسم interactions، وهو الاسم الداخلي الأقدم للكائن نفسه. يستخدم هذا الدليل مصطلح التقييم في جميع أجزائه. تتطلب عمليات القراءة مفتاح Read (قراءة). يتطلب الرد والتعديل والأرشفة وتغيير الإعدادات مفتاح Write (كتابة)؛ ويؤدي استخدام مفتاح Read في عملية كتابة إلى إرجاع 400 مع SY90016.
نظرة سريعة على نقاط النهاية
سرد مصادر التقييمات التي تسمح بها خطتك
تُرجع GET /reviews/site-config دليل منصات التقييمات التي يحق للحساب استخدامها. لا تقبل أي معاملات ويقتصر نطاقها على الحساب، لذا خزّن نتيجتها مؤقتًا بدلًا من استدعائها لكل موقع. قيم siteUrl هي أسماء المضيفين التي يقبلها كل عامل تصفية آخر في هذا المورد.
curl https://listingsapi.com/api/v4/reviews/site-config \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "interactionSiteConfig": [ { "site": "Google", "siteUrl": "maps.google.com" }, { "site": "Facebook", "siteUrl": "facebook.com" }, { "site": "Yelp", "siteUrl": "yelp.com" } ] }}اقرأ data.interactionSiteConfig[]. يعرض المثال حسابًا على خطة Launch؛ وتعتمد المجموعة الدقيقة على الخطة وقطاع النشاط. استخدم siteUrl لعامل التصفية siteUrls في نقاط نهاية القوائم، وللحقل siteUrls[].name عند تعديل الإعدادات.
سرد المصادر المهيّأة لموقع
تُرجع GET /locations/{locationId}/reviews/settings سجلًا واحدًا لكل منصة تدعمها الخطة، مع عنوان URL الذي تُجلب منه التقييمات. وهي جانب القراءة المقابل لنقطة نهاية التعديل أدناه. يقبل المسار المعرّف بترميز base64 أو الرقم العادي.
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/reviews/settings \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "interactionsSetting": { "siteSettings": [ { "name": "maps.google.com", "url": null }, { "name": "facebook.com", "url": null }, { "name": "yelp.com", "url": null } ] } }}اقرأ data.interactionsSetting.siteSettings[]. تعني قيمة url غير المساوية لـ null أن المنصة متصلة وأن التقييمات تُجلب من تلك الصفحة. عندما تكون قيمة url هي null، فهذا يعني أن المنصة متاحة لكنها غير مهيّأة. تُملأ بيانات Google وFacebook تلقائيًا عند ربط هذين الحسابين عبر OAuth، ولا يمكن الكتابة فوقها باستخدام نقطة نهاية التعديل. يجب تحديد Yelp صراحةً.
تعديل إعدادات التقييمات لموقع
تحدد POST /locations/reviews/settings/edit المصادر التي تُراقَب فيها تقييمات الموقع والتقييم بالنجوم الذي يُعدّ إيجابيًا. توضع الحقول مباشرةً في جسم الطلب، وليس داخل غلاف input. تؤدي إضافة مصدر إلى إدراج عملية استخلاص بيانات في قائمة الانتظار، لذا تصل تقييمات المنصة الجديدة لاحقًا، ولا تظهر في هذه الاستجابة.
curl -X POST https://listingsapi.com/api/v4/locations/reviews/settings/edit \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "positiveInteractionThreshold": 4, "siteUrls": [ { "name": "maps.google.com", "url": null }, { "name": "yelp.com", "url": "https://www.yelp.com/biz/blue-bottle-coffee-oakland" } ]}'{ "data": { "editInteractionsSetting": { "errors": null, "interactionSetting": { "locationId": "1800289", "positiveInteractionThreshold": 4, "siteSettings": [ { "name": "maps.google.com", "url": null, "monitored": true, "canRespond": true }, { "name": "yelp.com", "url": "https://www.yelp.com/biz/blue-bottle-coffee-oakland", "monitored": true, "canRespond": false } ] } } }}اقرأ data.editInteractionsSetting.interactionSetting.siteSettings[] للاطلاع على الاختيار المخزّن. يشير monitored إلى أن المصدر نشط؛ ويبيّن canRespond ما إذا كان يمكن نشر ردود المالك فيه عبر API. يُعاد المصدر الذي يرفضه التحقق من الصحة، مثل عنوان URL يتعذر الوصول إليه أو منصة غير مشمولة بالخطة، ضمن errors مع بقاء الإعداد دون تغيير، لذا تحقّق من errors عند تلقي 200. تُطلق حزم SDK الاستثناء ValidationError في هذه الحالة.
سرد التقييمات لموقع
GET /locations/{locationId}/reviews هو اتصال قائم على المؤشرات عند data.interactions، بترتيب الأحدث أولًا. القيمة الافتراضية لـ first هي 20، لذا لا يجلب استدعاء واحد السجل الكامل مطلقًا. تُمرَّر مرشحات المصفوفات كسلاسل JSON في سلسلة الاستعلام، ويجب ترميزها وفق ترميز URL؛ ويستخدم مثال cURL الخيار -G مع --data-urlencode لهذا الغرض.
بالإضافة إلى المعاملات الاختيارية category وcategories وratingFilter ذي القيمة الواحدة، المدرجة في الصفحة المرجعية.
curl -G "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/reviews" \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'ratingFilters=[1,2]' \--data-urlencode 'responseStatus=["PENDING"]' \--data-urlencode 'sortOrder=["NEWEST_FIRST"]' \--data-urlencode 'first=25'{ "data": { "interactions": { "pageInfo": { "hasNextPage": true, "endCursor": "SW50ZXJhY3Rpb246MV8xNTU0..." }, "edges": [ { "node": { "id": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "source": "maps.google.com", "content": "nice place for family together", "authorName": "vaibhav nakate", "rating": 5, "date": "2019-04-02T22:11:13.036997+00:00", "type": "Review", "responded": false, "responseCount": 0, "canRespond": true, "permalink": "https://maps.google.com/maps?cid=..." }, "cursor": "SW50ZXJhY3Rpb246MV8xNTU0..." } ], "totalCount": 425 } }}اقرأ edges[].node. تمرّر id عند الرد، ويبيّن canRespond ما إذا كان ذلك المصدر يقبل ردود المالك. يمثّل totalCount عدد النتائج المطابقة في مجموعة النتائج بأكملها، وليس في هذه الصفحة. توقّف عن التنقل بين الصفحات عندما تكون قيمة hasNextPage هي false أو عندما تُرجع صفحةٌ edges فارغًا؛ فإذا وقع حدّ الصفحة عند أقدم تقييم، تتبعه صفحة فارغة واحدة.
فحص جميع المواقع باستخدام التجميع
GET /rollup_interactions هو الاتصال نفسه القائم على المؤشرات عبر جميع المواقع التي يمكن للمفتاح الوصول إليها، عند data.rollupInteractions، مع locationId رقمي في كل عقدة. يقبل المرشحات نفسها التي تقبلها القائمة الخاصة بكل موقع. لا يوجد مرشح للموقع؛ ويُتجاهل المعامل locationIds ولا يُرفض. لا توفّر أيٌّ من حزمتي SDK دالةً تغلّف نقطة النهاية هذه حتى الآن، لذا تستخدم الأمثلة requests وfetch.
curl -G "https://listingsapi.com/api/v4/rollup_interactions" \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'responseStatus=["PENDING"]' \--data-urlencode 'sortOrder=["NEWEST_FIRST"]' \--data-urlencode 'first=50'{ "data": { "rollupInteractions": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "node": { "id": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "source": "maps.google.com", "content": "Excellent service, highly recommend.", "rating": 5, "responded": false, "canRespond": true, "locationId": 1800289 }, "cursor": "SW50ZXJhY3Rpb246OWUyNmQyYTg=" } ], "totalCount": 1284 } }}جمّع العقد حسب locationId، وهو databaseId الخاص بالمتجر. قد لا يتضمن pageInfo الخاص بالتجميع الحقل endCursor، لذا استخدم cursor الخاص بآخر عنصر edge بوصفه after؛ فالقيمتان متكافئتان. حدّد نطاق عمليات التشغيل المجدولة باستخدام startDate وendDate بدلًا من إعادة قراءة السجل، والتزم بـ Retry-After عند تلقي 429.
جلب التقييمات حسب id
يُرجع GET /reviewDetails نسخًا محدّثة من التقييمات المخزّنة دون تقسيمها إلى صفحات. الاستجابة مصفوفة عادية عند data.interactionDetails.interactions، دون edges أو pageInfo، ويتضمن كل تقييم responses الخاص به. استخدمه لإعادة جلب البيانات الحالية لقائمة متابعة وللعثور على responseId الذي تحتاج إليه للتعديل أو الأرشفة.
curl -G "https://listingsapi.com/api/v4/reviewDetails" \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'interactionIds=["b2fa765e-c62b-4e0b-b1d6-1c67c855f5e0"]'{ "data": { "interactionDetails": { "interactions": [ { "id": "b2fa765e-c62b-4e0b-b1d6-1c67c855f5e0", "source": "maps.google.com", "content": "Great place for dessert!", "rating": 5, "responded": true, "responseCount": 1, "canRespond": true, "responses": [ { "id": "2090753a-ece6-4837-8336-8494ad308523", "content": "Thank you so much for the kind words!", "interactionStatus": "CONFIRMED", "editedResponse": false } ] } ] } }}responses[].id هو responseId لنقطتي نهاية التعديل والأرشفة. عند تمرير id من حساب آخر، تُرجع نقطة النهاية 200 مع interactionDetails: null وخطأ SY90001، لذا تحقّق من null قبل الوصول إلى العناصر باستخدام الفهرس.
حقول التقييم والرد
مرجع السمات صفحة توثيق فقط تسرد جميع الحقول في كائن التقييم وكائن الرد. الحقول التي ستستخدمها أكثر من غيرها:
يتضمن كل رد في responses[] الحقول id وcontent وauthorName وdate وinteractionStatus وeditedResponse وrespondedWith (معرّف القالب) وremarks (تفاصيل الفشل). ينتقل interactionStatus بين الحالات التالية:
نشر رد من المالك
ينشر POST /locations/reviews/respond ردًا عامًا على المنصة المصدر. تُوضع الحقول مباشرةً في جسم الطلب. يُقبل الرد فورًا ويُسلَّم بصورة غير متزامنة، لذا يبدأ interactionStatus بالقيمة CREATED. تحقّق أولًا من canRespond في التقييم.
curl -X POST https://listingsapi.com/api/v4/locations/reviews/respond \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "interactionId": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "responseContent": "Thank you for visiting Jenny Home: we are glad you enjoyed your experience!"}'{ "data": { "respondToInteraction": { "interaction": { "id": "2090753a-ece6-4837-8336-8494ad308523", "interactionId": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "content": "Thank you for visiting Jenny Home: we are glad you enjoyed your experience!", "interactionStatus": "CREATED", "editedResponse": false }, "errors": null } }}احتفظ بـ interaction.id: فهو responseId المستخدم للتعديل والأرشفة. يُعاد الرد المرفوض بصيغة 200 مع تعبئة errors داخل data.respondToInteraction، لذا اقرأ جسم الاستجابة؛ وتُطلق حزم SDK الاستثناء ValidationError. أعد قراءة التقييم باستخدام معرّفه بعد انتظار قصير لرؤية الرد يصل إلى COMPLETED أو CONFIRMED.
تعديل رد
يغيّر POST /locations/reviews/respond/edit نص رد موجود. يُعاد إرسال التعديل إلى المنصة، لذا يعود interactionStatus إلى CREATED ويصبح editedResponse بالقيمة true بمجرد وصول التعديل إليها. يُفضَّل استخدام هذا الإجراء على الأرشفة وإعادة النشر في المنصات التي تسمح برد واحد.
curl -X POST https://listingsapi.com/api/v4/locations/reviews/respond/edit \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "reviewId": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "responseId": "2090753a-ece6-4837-8336-8494ad308523", "responseContent": "Thank you again: we have updated our reply to include our new store hours."}'{ "data": { "editResponse": { "status": "true", "reviewId": "9e26d2a8-a6ed-42ea-8454-47d1c92ea841", "responseId": "2090753a-ece6-4837-8336-8494ad308523" } }}تكون قيمة status هي السلسلة النصية "true" عند قبول التعديل. تأكّد من الصياغة الجديدة باستدعاء جلب التفاصيل وتحقّق من interactionStatus الخاص بالرد.
أرشفة رد
يزيل POST /locations/reviews/respond/archive ردًا من responses الذي نتتبّعه للتقييم من جانبنا. هذا حذف منطقي: فالرد المنشور بالفعل على Google أو Yelp أو Facebook يبقى هناك. استخدمه لإزالة مسودة فشلت أو حلّت محلها مسودة أخرى؛ واستخدم التعديل لأي رد منشور.
curl -X POST https://listingsapi.com/api/v4/locations/reviews/respond/archive \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "responseId": "2090753a-ece6-4837-8336-8494ad308523" }'{ "data": { "archiveResponse": { "status": "true" } }}بعد الأرشفة، ينخفض responseCount الخاص بالتقييم ويعكس responded الردود المتبقية.
عرض العبارات التي يكررها العملاء
يُرجع GET /review-phrases مصفوفة بسيطة في data.newReviewPhrases، تضم عنصرًا واحدًا لكل عبارة متكررة، ولكل عنصر إحصاءات محسوبة على التقييمات التي تحتوي على تلك العبارة فقط. النتائج غير مقسّمة إلى صفحات؛ حدّد حدها الأقصى باستخدام phraseCount. كل عوامل التصفية اختيارية ويمكن جمعها، لذا فإن استخدام ratingFilters=[1,2] مع startDate يعطي شكاوى الربع السابق.
بالإضافة إلى categories الاختياري والمعاملين المهملين ذوي القيمة الواحدة category وratingFilter المذكورين في الصفحة المرجعية.
curl -G "https://listingsapi.com/api/v4/review-phrases" \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'locationIds=[1800289]' \--data-urlencode 'ratingFilters=[1,2]' \--data-urlencode 'startDate=2026-06-01' \--data-urlencode 'endDate=2026-08-31' \--data-urlencode 'phraseCount=10'{ "data": { "newReviewPhrases": [ { "reviewPhrase": "friendly staff", "phraseStats": { "stats": [ { "name": "total-reviews", "value": 46, "delta": 12.5, "abs": 5 }, { "name": "overall-rating", "value": 4.7, "delta": 1.1, "abs": 0.05 } ] } }, { "reviewPhrase": "long wait", "phraseStats": { "stats": [ { "name": "total-reviews", "value": 11, "delta": 37.5, "abs": 3 }, { "name": "overall-rating", "value": 2.9, "delta": -8.4, "abs": -0.27 } ] } } ] }}يمثّل total-reviews عدد مرات ظهور العبارة، ويمثّل overall-rating متوسط تقييم تلك التقييمات، ويمثّل delta نسبة التغيّر مقارنةً بالفترة السابقة، ويمثّل abs مقدار التغيّر المطلق. تعني استجابة 403 المصحوبة بـ SY90003 أن المفتاح لا يتيح قراءة أحد المواقع المطلوبة.
قراءة مؤشرات الأداء الرئيسية للتقييمات لموقع
يُرجع GET /locations/{locationId}/review-analytics-overview أربعة إحصاءات في data.interactionsAnalyticsStats.stats. النطاق الزمني اختياري؛ وهو يضيّق الفترة التي تُحسب خلالها القيم ومقادير تغيّرها. يمثّل كل delta نسبة التغيّر مقارنةً بالفترة السابقة المساوية لها في الطول.
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/review-analytics-overview?startDate=2026-08-01&endDate=2026-08-31" \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "interactionsAnalyticsStats": { "stats": [ { "name": "total-reviews", "value": 128, "delta": 6.67 }, { "name": "new-reviews", "value": 9, "delta": -25 }, { "name": "overall-rating", "value": 4.43, "delta": 2.31 }, { "name": "review-response-rate", "value": 62.5, "delta": 12.5 } ] } }}يُظهر الحساب الجديد الذي لا تتوفر له فترة سابقة قيمة 100 في delta، لذا لا تفسّر مقادير التغيّر في الشهر الأول على أنها نمو.
جلب التسلسل الزمني اليومي للتقييمات
يعيد GET /locations/{locationId}/review-analytics-timeline عنصرًا واحدًا لكل يوم في data.interactionsChartData.data. مرّر startDate وendDate كلما كان النطاق الزمني للمخطط مهمًا؛ فحذفهما يتيح للخدمة اختيار نطاقها الزمني بنفسها. أضف site لرسم بيانات مصدر واحد بمفرده.
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/review-analytics-timeline?startDate=2026-08-01&endDate=2026-08-31&site=maps.google.com" \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "interactionsChartData": { "data": [ { "date": "2026-08-01", "interactionCount": 4, "averageRating": 4.5 }, { "date": "2026-08-02", "interactionCount": 0, "averageRating": null }, { "date": "2026-08-03", "interactionCount": 7, "averageRating": 4.285714285714286 } ] } }}ارسم interactionCount على هيئة أعمدة وaverageRating على هيئة خط. يخص المتوسط ذلك اليوم وحده، وليس متوسطًا تراكميًا، وتكون قيمته null في اليوم الذي لا توجد فيه تقييمات، لذا اترك فجوة بدلًا من رسم قيمة صفر.
تفصيل تحليلات التقييمات حسب المصدر
يعيد GET /locations/{locationId}/review-analytics-sites-stats عنصرًا واحدًا لكل مصدر تقييمات في data.interactionsSitesStats.stats. استخدمه لمعرفة المنصة التي غيّرت المتوسط.
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/review-analytics-sites-stats?startDate=2026-08-01&endDate=2026-08-31" \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "interactionsSitesStats": { "stats": [ { "key": "google", "siteUrl": "maps.google.com", "averageRating": { "value": 4.6, "delta": 2.2 }, "totalInteractions": { "value": 412, "delta": 6.1 }, "newInteractions": { "value": 24, "delta": 33.3 }, "recency": "2026-09-06T14:12:00Z", "baseRating": 4.5, "baseInteractions": 388, "humanizedRecency": "3 days ago" }, { "key": "facebook", "siteUrl": "facebook.com", "averageRating": { "value": 4.1, "delta": -1.4 }, "newInteractions": { "value": 0, "delta": -100 }, "recency": null, "humanizedRecency": null } ] } }}يتضمن كلٌّ من averageRating وtotalInteractions وnewInteractions قيمة value وقيمة delta؛ أما baseRating وbaseInteractions فهما القيمتان عند بداية الفترة التي يُقاس التغيّر انطلاقًا منها. يمثّل recency الطابع الزمني لأحدث تقييم، وتكون قيمته null إذا لم يُعِد المصدر أي تقييم مطلقًا. عادةً ما يعني وجود newInteractions بقيمة 0 مع recency يعود إلى عدة أشهر أن الاتصال بالمصدر لم يعد محدّثًا، لذا تحقّق من مصادر الموقع.
الأخطاء التي ستواجهها
قد تعيد عمليات الكتابة أيضًا 200 مع تعبئة errors داخل data.<op>، لذا اقرأ جسم الاستجابة لكل عملية كتابة. تتوفّر القائمة الكاملة في رموز الأخطاء.
الخطوات التالية
- جلب التقييمات: أنشئ قائمة انتظار للتقييمات المعلّقة وتلقَّ إشعارات عبر webhook.
- الردّ على التقييمات: الردّ والتأكيد والتعديل والأرشفة.
- تحليلات التقييمات: بطاقة مؤشرات، ومخطط، ولوحة شكاوى، ولقطات يومية.
- التحليلات: مقاييس الملف التجاري على Google وFacebook وBing للموقع نفسه.
- الصفحة الرئيسية للمرجع: التقييمات. حزم SDK: التقييمات في Python، التقييمات في Node.