إدراجات الأنشطة التجارية

كل نقاط نهاية Listings API بأمثلة cURL وPython وNode: حالة مزامنة منصات النشر المميزة، والمساعدات الصوتية، وكشف التكرار لكل موقع وحساب ومنعه.

إدراج النشاط التجاري هو سجل موقع واحد في دليل منصة نشر واحدة. يؤدي إنشاء موقع إلى وضع إدراج نشاط تجاري في قائمة الانتظار لكل منصة نشر ضمن خطتك، وتتيح نقاط نهاية إدراجات الأنشطة التجارية قراءة حالة كل إدراج، وسرد الإدراجات المكررة التي عُثر عليها، وتأكيدها أو رفض اعتبارها مكررة. تعمل نقاط النهاية الأربع GET بمفتاح Read (قراءة)؛ وتحتاج نقطتا النهاية POST إلى مفتاح Write (كتابة).

نظرة سريعة على نقاط النهاية

الطريقةالمسارالوظيفةالمرجع
GET/locations/{locationId}/listings/premiumحالة مزامنة موقع مع كل منصة نشر مميزة.جلب إدراجات الأنشطة التجارية المميزة
GET/locations/{locationId}/voice-assistantsحالة المزامنة على Google Assistant وAlexa وSiri وCortana وBixby.جلب إدراجات الأنشطة التجارية لدى المساعدات الصوتية
GET/locations/listings/duplicatesملخص مقسّم إلى صفحات للإدراجات المكررة المكتشفة على مستوى الحساب بأكمله.جلب جميع إدراجات الأنشطة التجارية المكررة لحساب
GET/locations/{locationId}/listings/duplicatesالإدراجات المكررة لموقع واحد، مجمّعة حسب الموقع الإلكتروني.جلب إدراجات الأنشطة التجارية المكررة لموقع
POST/locations/listings/mark-as-duplicateتأكيد أن عناصر إدراجات الأنشطة التجارية مكررة لمنع ظهورها.وضع علامة على إدراج نشاط تجاري باعتباره مكررًا
POST/locations/listings/mark-as-not-duplicateرفض اعتبار عناصر إدراجات الأنشطة التجارية مكررة لأن اكتشافها كان خاطئًا.وضع علامة على إدراج نشاط تجاري باعتباره غير مكرر

قراءة حالة إدراجات الأنشطة التجارية المميزة

GET /locations/{locationId}/listings/premium

تُرجع سجلًا واحدًا لكل منصة نشر مميزة ضمن خطة الموقع، تحت data.listingsForLocation. وهي مصفوفة عادية، وليست قائمة مقسّمة إلى صفحات. يُرجع المسار الموازي /listings/additional الأدلة المجانية بالبنية نفسها؛ ولا يوجد معامل استعلام listingType، وتُتجاهل أي قيمة تُرسل فيها.

المعاملات

الاسمالموضعمطلوبملاحظات
locationIdpathنعممعرّف بصيغة base64 أو databaseId رقمي.
Premium listings
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/listings/premium \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "listingsForLocation": [      {        "id": "TGlzdGluZzoxMDQ0Njg3MjM=",        "site": { "databaseId": "1", "name": "Google Maps", "url": "maps.google.com" },        "syncStatus": "REQUIRING_ACTION",        "displayStatus": "Connect your account to sync the listing",        "actionRequired": true,        "listingUrl": null,        "syncIssue": null,        "lastUpdate": "2026-07-06T18:33:28Z"      },      {        "id": "TGlzdGluZzoxMDQ0Njg3Mjc=",        "site": { "databaseId": "387", "name": "BeLocalFocussed", "url": "belocalfocussed.com" },        "syncStatus": "SYNCED",        "displayStatus": "Synced",        "actionRequired": false,        "listingUrl": "https://belocalfocussed.com/jenny-home-26x0ffkd0e",        "syncIssue": null,        "lastUpdate": "2026-07-06T18:33:30Z"      },      {        "id": "TGlzdGluZzoxMDQ0Njg3MDk=",        "site": { "databaseId": "301", "name": "Local Mint", "url": "localmint.com" },        "syncStatus": "FAILED",        "displayStatus": "Partner experiencing issues; awaiting response",        "actionRequired": false,        "listingUrl": null,        "syncIssue": "Publisher requires website URL",        "lastUpdate": "2026-07-06T18:34:03Z"      }    ]  }}

حدّد مسار المعالجة بناءً على syncStatus. اعرض displayStatus للمستخدم، واقرأ syncIssue لمعرفة السبب الذي تقدمه منصة النشر، واستخدم lastUpdate لاكتشاف عملية إرسال متوقفة. لا تُعيّن قيمة listingUrl إلا في الصفوف المنشورة فعليًا.

syncStatusالمعنى
AVAILABLEجاهز للمزامنة، ولم تبدأ بعد.
IN_PROGRESSأُرسل إلى منصة النشر، وفي انتظار رد.
PENDING_APPROVALتراجعه منصة النشر.
SYNCED أو COMPLETEDمنشور فعليًا. يحتوي listingUrl على قيمة.
REQUIRING_ACTIONمتوقف بانتظار إجراء منك. قيمة actionRequired هي true؛ اقرأ displayStatus.
FAILEDفشلت المزامنة. اقرأ syncIssue.
CANNOT_SUBMITلا تستطيع منصة النشر هذه قبول هذا الموقع على الإطلاق.

تظل Google Maps وFacebook وWaze في حالة REQUIRING_ACTION مع displayStatus: "Connect your account to sync the listing" إلى أن يُربط الحساب المقابل. وهذا متوقع لموقع جديد.

قراءة حالة المساعدات الصوتية

GET /locations/{locationId}/voice-assistants

تُرجع سجلًا واحدًا لكل مساعد صوتي تحت data.voiceAssistantsForLocation: Google Assistant وAmazon Alexa وApple Siri وMicrosoft Cortana وSamsung Bixby. وهي مصفوفة عادية ذات مجموعة حالات أقل من نقطة نهاية الإدراجات المميزة.

المعاملات

الاسمالموضعمطلوبملاحظات
locationIdpathنعممعرّف بصيغة base64 أو databaseId رقمي.
Voice assistants
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/voice-assistants \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "voiceAssistantsForLocation": [      {        "databaseId": "104468723",        "voiceIdentifier": "GOOGLE_ASSISTANT",        "name": "Google Assistant",        "connectedAccountId": null,        "syncStatus": "REQUIRING_ACTION",        "actionRequired": true,        "syncIssue": null,        "errors": []      },      {        "databaseId": "104468711",        "voiceIdentifier": "SIRI",        "name": "Siri",        "connectedAccountId": null,        "syncStatus": "IN_PROGRESS",        "actionRequired": false,        "syncIssue": null,        "errors": []      }    ]  }}

ضع علامة على كل صف تكون فيه قيمة actionRequired هي true أو تكون فيه قيمة syncIssue معيّنة. يحتوي errors على نصوص الأخطاء من جانب منصة النشر، ويحدّد connectedAccountId اسم الحساب المرتبط الذي تتم المزامنة من خلاله، عندما ينطبق ذلك. تأتي نتائج Google Assistant من الربط مع Google Business Profile، لذا فإن عدم وجود ربط مع Google هو السبب الأكثر شيوعًا لحاجته إلى الانتباه. تأتي نتائج Siri من إدراج النشاط التجاري الخاص بالموقع على Apple Maps.

syncStatusالمعنى
NOT_SUBMITTEDلم يُرسل إلى المساعد بعد.
IN_PROGRESSالإرسال جارٍ.
REQUIRING_ACTIONيلزم إدخال من العميل قبل أن تتمكن المزامنة من المتابعة.
LIVEمنشور. لا يوجد رابط منشور لإدراج النشاط التجاري لدى مساعد صوتي.

تجميع النسخ المكررة على مستوى الحساب

GET /locations/listings/duplicates

يُرجع كل نسخة مكررة مكتشفة يمكن للمفتاح الاطلاع عليها، عبر جميع المواقع ومنصات النشر، ضمن data.duplicateListingsRollup. تُستخدم فيه صفحات قائمة على الإزاحة: يستقبل page وperPage، ويُرجع records[] بالإضافة إلى pageInfo.totalRecords وpageInfo.totalPages وpageInfo.hasNextPage. عوامل التصفية هي معاملات استعلام مسطحة، وليست JSON. عند عدم تقديم أي معاملات، تكون القيمة الافتراضية لـ status هي POTENTIAL ولـ tag هي all، لذا يُرجع الاستدعاء دون معاملات النسخ المكررة المفتوحة في الحساب.

المعاملات

الاسمالموضعمطلوبملاحظات
statusqueryلاPOTENTIAL (القيمة الافتراضية)، أو PROCESSING، أو FIXED، أو FAILED. لا يُميّز بين الأحرف الكبيرة والصغيرة. تؤدي أي قيمة أخرى إلى 400.
siteIdqueryلاحصر النتائج في منصة نشر واحدة باستخدام معرّف موقعها الرقمي (site.databaseId من نقطة نهاية premium، أو معرّف plan-sites).
tagqueryلاحصر نطاق التجميع في وسم واحد. القيمة الافتراضية هي all.
pagequeryلارقم الصفحة، بدءًا من 1. القيمة الافتراضية هي 1.
perPagequeryلاعدد السجلات في كل صفحة.

تتيح أغلفة Python وNode المعاملين tag وpage فقط. للتصفية حسب status أو siteId، أو لتعيين perPage، استدعِ المسار مباشرةً كما هو موضح في التعامل مع إدراجات الأنشطة التجارية المكررة.

Account rollup
curl "https://listingsapi.com/api/v4/locations/listings/duplicates?status=POTENTIAL&page=1&perPage=50" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "duplicateListingsRollup": {      "pageInfo": {        "hasNextPage": true,        "hasPreviousPage": false,        "totalPages": 34,        "totalRecords": 1673      },      "records": [        {          "id": "3329229",          "name": "Woodbury Train Station",          "nameValid": false,          "duplicateProcessingState": "POTENTIAL",          "liveLink": "http://citysquares.com/b/woodbury-train-station-23598450",          "locationId": "73451",          "siteName": "City Squares",          "siteUrl": "citysquares.com"        }      ]    }  }}

يوضح التجميع مواضع النسخ المكررة: يحدد كل سجل locationId وsiteName. تمثل duplicateProcessingState حالة دورة الحياة نفسها التي تُرجعها نقطة النهاية الخاصة بكل موقع باسم status. تنقّل بين الصفحات، صفحةً واحدةً في كل مرة، حتى تصبح قيمة hasNextPage هي false؛ فالحلقة المتتابعة دون توقف هي أسرع طريق إلى 429.

الحالةالمعنى
POTENTIALاكتُشفت النسخة المكررة، ولم يتخذ أحد إجراءً بشأنها.
PROCESSINGتأكد أنها نسخة مكررة؛ ويجري العمل مع منصة النشر على إخفائها.
FIXEDأزالتها منصة النشر أو دمجتها.
FAILEDلم تنجح عملية الإخفاء. تحقّق من liveLink.

سرد النسخ المكررة لموقع واحد

GET /locations/{locationId}/listings/duplicates

يُرجع كل نسخة مكررة مكتشفة لموقع واحد ضمن data.duplicateListingsForLocation، مجمّعة حسب موقع منصة النشر. النتيجة مصفوفة بسيطة. تمثل كل مجموعة موقعًا (name، url) مع مصفوفة listings، ويحمل كل عنصر قيمة listingItemId التي تقبلها نقطتا نهاية وضع العلامات. تعني المصفوفة الفارغة أنه لم يُكتشف أي شيء.

المعاملات

الاسمالموضعمطلوبملاحظات
locationIdpathنعممعرّف بترميز Base64 أو databaseId رقمي.
Duplicates for a location
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/listings/duplicates \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "duplicateListingsForLocation": [      {        "id": "U2l0ZToxNTA=",        "name": "City Squares",        "url": "citysquares.com",        "listings": [          {            "id": "RHVwbGljYXRlOjIzNTk4NDUw",            "listingItemId": "TGlzdGluZ0l0ZW06MjM1OTg0NTA=",            "name": "Woodbury Train Station",            "liveLink": "http://citysquares.com/b/woodbury-train-station-23598450",            "status": "POTENTIAL"          }        ]      }    ]  }}

افتح liveLink لمراجعة العنصر، ثم احتفظ بـ listingItemId. في Node SDK، تكون d.id الناتجة عن التسطيح هي القيمة التي يجب تمريرها لاحقًا. يستخدم status القيم الأربع نفسها التي يستخدمها التجميع على مستوى الحساب أعلاه.

تأكيد أن عناصر إدراجات الأنشطة التجارية مكررة

POST /locations/listings/mark-as-duplicate

يضع علامة على عناصر إدراجات الأنشطة التجارية لتأكيد أنها مكررة، حتى يمكن إخفاؤها بالتنسيق مع منصة النشر. أرسل قيم listingItemId ضمن input، واجمع كل العناصر المؤكد تكرارها لموقع واحد في استدعاء واحد بدلًا من استدعاء لكل عنصر. هذه عملية كتابة وتتطلب مفتاح Write (كتابة).

المعاملات

الاسمالموضعمطلوبملاحظات
input.listingItemIdsbodyنعممصفوفة من قيم listingItemId بترميز base64 من نقاط نهاية النسخ المكررة.
input.locationIdbodyلامعرّف موقع بترميز Base64 أو معرّف رقمي. يحصر العملية في موقع واحد.
Mark as duplicate
curl -X POST https://listingsapi.com/api/v4/locations/listings/mark-as-duplicate \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "listingItemIds": ["TGlzdGluZ0l0ZW06MjM1OTg0NTA="]  }}'
JSON
{  "data": {    "markAsDuplicate": {      "success": true,      "errors": null    }  }}

تعني success: true أن العناصر قُبلت وتنتقل إلى PROCESSING. عند إرجاع 200 مع success: false، أو 400، تتضمن الاستجابة مصفوفة errors تحمل عناصرها code وmessage وpath؛ ويكون السبب المعتاد معرّفًا غير معروف أو غير صحيح الصيغة. تُرجع Python SDK الحمولة؛ أما Node SDK فتطرح ValidationError بدلًا من ذلك، لذا فإن اكتمال promise بنجاح يعني نجاح العملية.

استبعاد عناصر إدراجات الأنشطة التجارية باعتبارها غير مكررة

POST /locations/listings/mark-as-not-duplicate

يستبعد النسخ المكررة المحتملة باعتبارها نتائج إيجابية كاذبة. تتوخى عملية الاكتشاف الحذر، وستضع علامة على فرع آخر للامتياز التجاري نفسه، أو ملف تجاري ثانٍ مشروع، أو موقع تغيّر اسمه. بمجرد استبعاد العناصر، تتوقف عن الظهور في كلتا نقطتي نهاية النسخ المكررة. يقبل جسم الطلب نفسه الذي تقبله نقطة النهاية أعلاه، ويُستخدم أيضًا للتراجع عن وضع علامة على عنصر عن طريق الخطأ.

المعاملات

الاسمالموضعمطلوبملاحظات
input.listingItemIdsbodyنعممصفوفة من قيم listingItemId بترميز base64 المطلوب استبعادها.
input.locationIdbodyلامعرّف موقع بترميز Base64 أو معرّف رقمي. يحصر العملية في موقع واحد.
Mark as not duplicate
curl -X POST https://listingsapi.com/api/v4/locations/listings/mark-as-not-duplicate \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "listingItemIds": ["TGlzdGluZ0l0ZW06MjM1OTg0NTA="]  }}'
JSON
{  "data": {    "markAsNotDuplicate": {      "success": true,      "errors": null    }  }}

الاستجابة هي data.markAsNotDuplicate، وتتضمن حقلي success وerrors نفسيهما اللذين يتضمنهما استدعاء وضع علامة على العنصر باعتباره مكررًا. يُسجَّل العنصر المستبعد باعتباره عنصرًا مؤكدًا غير مكرر، ولا يعود إلى الظهور في جولة الاكتشاف التالية.

الأخطاء التي ستواجهها

الرمز أو الحالةالمعنىالحل
401مفتاح API مفقود أو غير صالح.أرسل Authorization: API $LISTINGSAPI_KEY.
400 في الملخص التجميعي للحسابstatus ليس إحدى القيم POTENTIAL، PROCESSING، FIXED، FAILED.استخدم إحدى القيم الأربع.
400 في نقطة نهاية markمعرّف عنصر إدراج النشاط التجاري غير معروف أو غير صحيح التنسيق. اقرأ errors[].code وmessage.أرسل قيم listingItemId من نقاط نهاية الإدراجات المكررة للأنشطة التجارية.
200 مع success: falseنُفّذ الطلب، لكن رُفضت المدخلات. التفاصيل موجودة في data.<op>.errors.تحقق من محتوى الاستجابة لكل عملية كتابة، وليس من الحالة فقط.
SY90016 (HTTP 400)استخدام مفتاح Read في عملية كتابة.استخدم مفتاح Write لنقطتي نهاية mark.
429تم تجاوز حد معدل الطلبات. تسمح خطة Launch بإرسال 10 طلبات في الدقيقة.انتظر Retry-After، ثم استأنف. راجع حدود معدل الطلبات.

كل رمز مدرج في مرجع الأخطاء.

الخطوات التالية