الحسابات المتصلة

كل نقاط نهاية الحسابات المتصلة بأمثلة cURL وPython وNode: ربط Google وFacebook، سرد الحسابات، مطابقة إدراجات نشاط تجاري وربطها، مجلدات، إنشاء GMB، فصل.

الحساب المتصل هو تفويض OAuth يمنحه مالك حساب Google Business Profile أو صفحات Facebook، ويتيح لواجهة API قراءة إدراجات الأنشطة التجارية التي يمكن لذلك الحساب الوصول إليها وإدارتها. يغطي هذا المورد ثلاث مهام: إنشاء روابط OAuth، ومطابقة إدراجات الأنشطة التجارية التابعة للحساب مع مواقعك أو ربطها بها، ثم قطع الاتصال. تعمل عمليتا القراءة GET للقائمة والتفاصيل بمفتاح Read (قراءة)؛ وتتطلب كل عملية POST مفتاح Write (كتابة)، بما في ذلك جلب إدراجات الأنشطة التجارية المخصص للقراءة فقط، ويؤدي استخدام مفتاح Read في عملية كتابة إلى إرجاع HTTP 400 مع SY90016.

يفترض كل مثال أدناه أن العميل أُنشئ مرة واحدة بالطريقة الموضحة في المثال الأول، ويقرأ LISTINGSAPI_KEY من البيئة. المعرّفات هي UUID الخاص بـ connectedAccountId من نقطة نهاية القائمة ومعرّف الموقع بترميز base64 ‏(TG9jYXRpb246MTgwMDI4OQ==)؛ لا تطبّق ترميز URL على أي منهما مطلقًا.

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

الطريقةالمسارالوظيفةالمرجع
POST/connected-accounts/connect-googleإنشاء رابط ربط جماعي لحساب Google صالح لمدة 24 ساعة.ربط حساب Google
POST/connected-accounts/connect-facebookإنشاء رابط ربط جماعي لحساب Facebook صالح لمدة 24 ساعة.ربط حساب Facebook
POST/locations/oauth_connect_urlإنشاء رابط ربط يُستخدم مرة واحدة ويرتبط بموقع واحد.عنوان URL لربط موقع واحد عبر OAuth
GET/connected-accountsعرض قائمة بالحسابات المتصلة مع حالة اتصالها وأعداد المواقع المرتبطة بها.عرض قائمة الحسابات المتصلة
GET/connected-accounts/{connectedAccountId}/detailsقراءة حساب واحد، بما في ذلك حالة مهمة المطابقة.الحصول على تفاصيل حساب متصل
POST/connected-accounts/connected-account-listingsعرض قائمة بإدراجات الأنشطة التجارية لدى منصات النشر التي يمكن للحساب الوصول إليها.جلب إدراجات الأنشطة التجارية لحساب متصل
POST/connected-accounts/trigger-matchesإضافة مهمة الجلب والمطابقة لحساب واحد أو أكثر إلى قائمة الانتظار.بدء مطابقة المواقع
GET/connected-accounts/{connectedAccountId}/connection-suggestionsقراءة أزواج المطابقة المقترحة بين المواقع وإدراجات الأنشطة التجارية.عرض قائمة اقتراحات الربط
POST/connected-accounts/confirm-matchesقبول الاقتراحات وإنشاء الروابط الفعلية.تأكيد مطابقات الربط
POST/connected-accounts/connect-listingربط إدراج نشاط تجاري واحد تختاره بموقع واحد.ربط إدراج نشاط تجاري بموقع
POST/connected-accounts/disconnect-listingإلغاء ربط موقع واحد بمنصة نشر واحدة.إلغاء ربط إدراج نشاط تجاري بموقع
POST/connected-accounts/create-location-from-listingإنشاء موقع جديد من إدراج نشاط تجاري لدى منصة نشر.إنشاء موقع من إدراج نشاط تجاري
GET/connected-accounts/{connectedAccountId}/foldersعرض قائمة مجموعات حساب Google (المجلدات).عرض قائمة مجلدات GMB
POST/locations/create/gmb-listingإنشاء ملف Google Business Profile جديد تمامًا لموقع.إنشاء إدراج نشاط تجاري على GMB
POST/connected-accounts/disconnect-googleقطع اتصال حساب Google بالكامل.قطع اتصال حساب Google
POST/connected-accounts/disconnect-facebookقطع اتصال حساب Facebook بالكامل.قطع اتصال حساب Facebook
POST/locations/oauth-disconnectقطع اتصال موقع واحد بمنصة نشر (العملية نفسها التي ينفذها disconnect-listing).قطع اتصال موقع واحد بمنصة نشر

POST /connected-accounts/connect-google

تُرجع عنوان URL لتفويض OAuth صالحًا لمدة قصيرة. أعد توجيه مالك الحساب إليه؛ ثم تعيده Google إلى successUrl أو errorUrl الخاص بك. يقتصر نطاق الرابط على الحساب الذي يملك مفتاح API، لذا لا يتضمن جسم الطلب سوى عنوانَي إعادة التوجيه الخاصين بك. تؤدي إعادة إصدار رابط لحساب انتهت صلاحية تفويضه إلى تجديد الاتصال الحالي بدلًا من إنشاء اتصال مكرر.

الاسمموضعهمطلوبملاحظات
inputbodyنعمكائن حاوٍ؛ يندرج جسم الطلب بأكمله تحته.
input.successUrlbodyنعمعنوان URL مطلق يستخدم https وتتحكم فيه. يُعاد التوجيه إليه بعد الموافقة.
input.errorUrlbodyنعمعنوان URL مطلق يستخدم https وتتحكم فيه. يُعاد التوجيه إليه عند الإلغاء أو الفشل.
Connect Google
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-google \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "successUrl": "https://app.example.com/connect/google/success",    "errorUrl": "https://app.example.com/connect/google/error"  }}'
JSON
{  "data": {    "bulkConnectLinkForGoogle": {      "success": true,      "url": "https://connect.example.com/oauth?token=8f3c1d92-...",      "errors": null    }  }}

القيمة url أعلاه مؤقتة للتوضيح. وجّه المالك إلى url الذي أُرجع في الاستجابة لطلبك.

الرابط صالح لمدة 24 ساعة. لا يُملأ errors إلا عند فشل الإنشاء، لذا تحقّق من أن قيمة url ليست null. يُرفض جسم الطلب غير المتداخل، أو الذي يتضمن accountId، مع إرجاع HTTP 400.

POST /connected-accounts/connect-facebook

هذه هي العملية المقابلة لـ Facebook، وتستخدم جسم الطلب نفسه. أثناء العملية، يقبل المالك شروط Facebook ويمنح أذونات إدارة الصفحات التي تحتاج إليها واجهة API؛ وإذا تخطّى أحد الأذونات، فلن يتمكن الاتصال من المزامنة، لذا أعد إصدار الرابط واطلب منه الموافقة مرة أخرى.

الاسمموضعهمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.successUrlbodyنعمعنوان URL مطلق يستخدم https وتتحكم فيه.
input.errorUrlbodyنعمعنوان URL مطلق يستخدم https وتتحكم فيه.
Connect Facebook
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-facebook \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "successUrl": "https://app.example.com/connect/facebook/success",    "errorUrl": "https://app.example.com/connect/facebook/error"  }}'
JSON
{  "data": {    "bulkConnectLinkForFacebook": {      "success": true,      "url": "https://connect.example.com/oauth?token=8f3c1d92-...",      "errors": null    }  }}

القيمة url أعلاه مؤقتة للتوضيح. وجّه المالك إلى url الذي أُرجع في الاستجابة لطلبك.

مفتاح الاستجابة هو bulkConnectLinkForFacebook؛ وبخلاف ذلك، اقرأ الاستجابة بالطريقة نفسها تمامًا المتبعة مع رابط Google. بمجرد أن يُكمل المالك العملية، يظهر الحساب في نقطة نهاية القائمة بوصفه FacebookAccount.

POST /locations/oauth_connect_url

استخدم هذا عندما تعرف مسبقًا الموقع الذي يربطه المالك. يرتبط الرابط بالموقع الذي تحدده، لذلك لا تتبعه خطوة مطابقة: عندما يوافق المالك، تُربط بيانات الاعتماد بذلك الموقع مباشرةً. أما رابطا الربط الجماعي أعلاه فيربطان حسابًا كاملًا.

الاسمالموضعمطلوبملاحظات
inputbodyنعمالكائن الحاوي.
input.locationIdbodyنعممعرّف الموقع بترميز Base64، أو المعرّف الرقمي الخام.
input.sitebodyنعمGOOGLE أو FACEBOOK أو APPLE.
input.successUrlbodyنعمعنوان URL مطلق يُنتقل إليه بعد منح التفويض.
input.errorUrlbodyنعمعنوان URL مطلق يُنتقل إليه عند الإلغاء أو الفشل.
Single-location link
curl -X POST https://listingsapi.com/api/v4/locations/oauth_connect_url \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "site": "GOOGLE",    "successUrl": "https://app.example.com/locations/1800289/connected",    "errorUrl": "https://app.example.com/locations/1800289/connect-failed"  }}'
JSON
{  "data": {    "createConnectUrl": {      "success": true,      "url": "https://connect.example.com/oauth?token=8f3c1d92-...",      "errors": null    }  }}

القيمة url أعلاه عنصر نائب. وجّه المالك إلى url الذي تُرجعه الاستجابة لطلبك.

الرابط صالح للاستخدام مرة واحدة، لذا أنشئ رابطًا جديدًا لكل محاولة بدلًا من تخزينه مؤقتًا. إذا كان عنوان URL لإعادة التوجيه نسبيًا أو غير قابل للتحليل، فتُرجع الاستجابة success: true مع null url، لذا تحقّق من url وليس من success فقط. إذا لم يكن المفتاح مخوّلًا بالوصول إلى هذا الموقع، فتُرجع الاستجابة الحالة 403 مع SY90003. تحوّل حزم SDK القيمة site إلى أحرف كبيرة تلقائيًا.

سرد الحسابات المرتبطة

GET /connected-accounts

يُرجع كل حساب مُنح تفويضًا ضمن حساب API الخاص بك، مع حالة الاتصال وعدد المواقع التي يرتبط بها كل حساب. تستخدم هذه الصفحة الإزاحة: records[] مع pageInfo.totalRecords، ويجري التنقل بين الصفحات باستخدام معاملي الاستعلام page وperPage دون تداخل. الترتيب ثابت وتصاعدي بحسب البريد الإلكتروني للحساب.

الاسمالموضعمطلوبملاحظات
pagequeryلارقم الصفحة، ويبدأ من 1. القيمة الافتراضية 1.
perPagequeryلاعدد السجلات في كل صفحة. القيمة الافتراضية 20.
publisherqueryلاGoogleAccount أو FacebookAccount أو AppleAccount أو YelpAccount أو TripadvisorAccount أو LinkedinAccount أو PinterestAccount أو TwitterAccount.
statusqueryلاConnected أو NotConnected أو ConnectionIssue. مزيج من الأحرف الكبيرة والصغيرة.
List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&status=Connected&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "totalPages": 1, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "connectedAccountType": "GoogleAccount",          "email": "owner@brightsmile-dental.com",          "status": "CONNECTED",          "connectivityIssue": null,          "connectedLocationsCount": 0,          "requestMatchesStatus": "MATCH_COMPLETED",          "lastFetchMatchesRequestedAt": "2026-07-06 21:43:07 UTC"        }      ]    }  }}

اختر السجل الذي يشير فيه email إلى المالك الذي وافق، واحتفظ بقيمة connectedAccountId فيه؛ فكل استدعاء لاحق يتطلبها. يُتجاهل أي شيء غير معاملات الاستعلام الأربعة بدلًا من رفضه، لذا فإن إرسال pageInfo بصيغة JSON يُرجع الصفحة 1 دون تنبيه.

status في السجلالمعنى
CONNECTEDبيانات الاعتماد صالحة. يمكن بدء المطابقة أو النشر بأمان.
MATCH_IN_PROGRESSعملية مطابقة في قائمة الانتظار أو قيد التنفيذ.
CONNECTIVITY_ISSUEانتهت صلاحية التفويض. يوضح connectivityIssue السبب؛ أصدِر رابط الربط مجددًا.

لا يستخدم عامل التصفية status والحقل status في السجل مجموعة القيم نفسها. استخدام CONNECTED مجددًا كقيمة لعامل التصفية يعطي قيمة غير صالحة للتعداد ويؤدي إلى إرجاع الحالة 400.

الحصول على تفاصيل حساب واحد

GET /connected-accounts/{connectedAccountId}/details

يُرجع الحقول نفسها الموجودة في سجل واحد من القائمة، ويقتصر نطاقه على حساب واحد. استخدمه للاستعلام دوريًا عن requestMatchesStatus بعد بدء المطابقة، أو للتحقق من status وconnectivityIssue قبل إرسال تحديث عبر الحساب.

الاسمالموضعمطلوبملاحظات
connectedAccountIdpathنعممعرّف UUID من نقطة نهاية سرد الحسابات.
Account details
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/details \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountDetails": {      "details": {        "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",        "connectedAccountType": "GoogleAccount",        "status": "CONNECTED",        "connectivityIssue": null,        "connectedLocationsCount": 0,        "requestMatchesStatus": "MATCH_COMPLETED"      }    }  }}

يوجد السجل داخل مستوى واحد عند data.connectedAccountDetails.details. تتغير قيمة requestMatchesStatus من MATCH_IN_PROGRESS إلى MATCH_COMPLETED عندما تصبح الاقتراحات جاهزة. تعني الحالة Completed أن أداة المطابقة انتهت، ولا تعني ربط أي شيء: تظل قيمة connectedLocationsCount هي 0 حتى تؤكد إدراج نشاط تجاري أو تربطه.

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

POST /connected-accounts/connected-account-listings

يسرد كل إدراج نشاط تجاري على Google Business Profile أو Facebook يمكن للحساب الوصول إليه، سواء كان مرتبطًا بأحد مواقعك أم لا. قيمة id في كل سجل هي connectedAccountListingId الذي يقبله كل من connect-listing وcreate-location-from-listing. هذا طلب POST يقتصر على القراءة، ويُرجع صفحة تستخدم الإزاحة: records[] مع pageInfo، ويجري التنقل بين الصفحات باستخدام المفتاحين page وperPage مباشرةً في جسم الطلب دون تداخل.

الاسمالموضعمطلوبملاحظات
connectedAccountIdbodyنعممعرّف UUID للحساب المراد جلب إدراجات الأنشطة التجارية الخاصة به. لا يُوضع داخل input.
pagebodyلارقم الصفحة. القيمة الافتراضية 1.
perPagebodyلاعدد السجلات في كل صفحة. القيمة الافتراضية 500، وهي الحد الأقصى أيضًا.
locationInfobodyلابحث بنص حر في الاسم والعنوان والمنطقة والرمز البريدي ورمز المتجر ورقم الهاتف.
Account listings
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connected-account-listings \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5", "perPage": 50, "locationInfo": "William St" }'
JSON
{  "data": {    "connectedAccountListings": {      "pageInfo": { "hasNextPage": false, "totalPages": 1, "totalRecords": 60 },      "records": [        {          "id": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA==",          "accountTypeName": "Google",          "locationName": "Trial",          "address": "123 William St, NY 10038, Manhattan, US",          "phone": "(718) 667-7787",          "liveLink": null        }      ]    }  }}

تنقّل بين صفحات المجموعة باستخدام pageInfo.hasNextPage وpageInfo.totalPages. تضع حزم SDK القيمة connectedAccountId في جسم الطلب تلقائيًا، لذا ينطبق هذا فقط على استدعاءات REST المكتوبة يدويًا.

بدء المطابقة

POST /connected-accounts/trigger-matches

يضيف إلى قائمة الانتظار المهمة التي تسترجع كل ملف شخصي تستطيع الحسابات المحددة الوصول إليه وتقرن كل ملف بأحد مواقعك. تشمل المطابقة كل موقع نشط وغير مؤرشف وغير متصل بالفعل. ولا تسجّل إلا اقتراحات؛ ولا يُنشأ أي ربط حتى تؤكّد.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.connectedAccountIdsbodyنعممصفوفة من معرّفات UUID للحسابات من نقطة نهاية القائمة.
Trigger matches
curl -X POST https://listingsapi.com/api/v4/connected-accounts/trigger-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountIds": ["4f712c17-4f95-42dd-90f4-97171a2e67b5"] } }'
JSON
{  "data": {    "connectedAccountsTriggerMatches": {      "success": true,      "failedIds": null    }  }}

تعني success: true أن المهمة أُضيفت إلى قائمة الانتظار، ولا تعني اكتمال المطابقة. يُدرج أي حساب تعذّرت إضافته إلى قائمة الانتظار في failedIds، وتكون قيمة success هي false. استعلم دوريًا من نقطة نهاية التفاصيل حتى تصبح قيمة requestMatchesStatus هي MATCH_COMPLETED قبل قراءة الاقتراحات؛ فالاستعلام كل 15 ثانية باستخدام حلقة ذات عدد تكرارات محدود يُبقي خطة Launch ضمن حدّها البالغ 10 طلبات في الدقيقة.

قراءة اقتراحات الربط

GET /connected-accounts/{connectedAccountId}/connection-suggestions

تُرجع أزواج المطابقة التي اقترحتها أداة المطابقة: موقعك في أحد الطرفين (locationInfo، حيث تكون locationId هي قيمة databaseId الخاصة به)، وإدراج النشاط التجاري على منصة النشر في الطرف الآخر (suggestedLocationInfo). هذه صفحة تعتمد على الإزاحة، ويُتحكّم في تقسيم النتائج إلى صفحات باستخدام معامِلَي الاستعلام غير المتداخلين page وperPage؛ والترتيب ثابت وتصاعدي بحسب معلومات الموقع.

الاسمالموضعمطلوبملاحظات
connectedAccountIdpathنعممعرّف UUID للحساب.
pagequeryلارقم الصفحة، بدءًا من 1. القيمة الافتراضية 1.
perPagequeryلاعدد السجلات في كل صفحة. القيمة الافتراضية 20.
Suggestions
curl "https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectionSuggestionsForAccount": {      "pageInfo": { "hasNextPage": false, "totalPages": 1, "totalRecords": 2 },      "records": [        {          "accountType": "GMB",          "matchedDataDatabaseId": "0d5e306f-0da0-46e3-929f-fd3c67ccd8cc",          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "locationId": "73415",          "locationInfo": { "name": "My Business", "city": "Lincoln", "stateIso": "NE" },          "suggestedLocationInfo": { "locationInfo": { "name": "My Business", "city": "Lincoln" } }        }      ]    }  }}

لا يحتوي الاقتراح على id. احتفظ بالقيمتين matchedDataDatabaseId وaccountType معًا؛ إذ تحتاج confirm-matches إلى كلتيهما لإنشاء المعرّف. إذا قرأت النتائج مبكرًا، قبل MATCH_COMPLETED، فستُرجع نقطة النهاية records: [] مع totalRecords: 0، وهي نتيجة تبدو مطابقة تمامًا لحالة "لم يُعثر على أي تطابق".

accountTypeمنصة النشرنوع سجل المطابقة
GMBGoogle Business ProfileGmbLocationMatchedData
FBصفحات FacebookFbLocationMatchedData
APPLEApple Business ConnectAppleLocationMatchedData

تأكيد المطابقات

POST /connected-accounts/confirm-matches

تقبل الاقتراحات التي توافق عليها وتُنشئ الروابط الفعلية. كل معرّف هو ناتج ترميز <MatchRecordType>:<matchedDataDatabaseId> باستخدام base64، مع اختيار النوع من الجدول أعلاه. يُستنتج الحساب من السجلات، لذا لا يوجد حقل connectedAccountId؛ ويُرفض أي حقل غير معروف داخل input بإرجاع الحالة 400.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ. الحقل الوحيد المعرَّف هو matchRecordIds.
input.matchRecordIdsbodyنعممصفوفة من معرّفات سجلات المطابقة المرمّزة باستخدام base64. معرّف واحد على الأقل.
Confirm matches
# base64 of GmbLocationMatchedData:0d5e306f-0da0-46e3-929f-fd3c67ccd8cccurl -X POST https://listingsapi.com/api/v4/connected-accounts/confirm-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "matchRecordIds": ["R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M="] } }'
JSON
{  "data": {    "confirmConnectMatches": {      "success": true,      "failedIds": null    }  }}

يحتوي failedIds على قيم matchedDataDatabaseId بعد فك ترميزها التي تعذّر تأكيدها، مثل سجل استُخدم بالفعل أو موقع أُرشف بعد المطابقة، لذا طابق هذه القيم مع سجلات الاقتراحات. تبقى الاقتراحات التي لم تُرسل دون تغيير. يربط التأكيد الموقع بإدراج النشاط التجاري؛ ولا يرسل البيانات إلى منصة النشر من تلقاء نفسه.

ربط إدراج نشاط تجاري واحد بموقع

POST /connected-accounts/connect-listing

تربط إدراج نشاط تجاري واحدًا اخترته بالفعل بموقع واحد، دون خطوة اقتراح أو تأكيد. استخدمها عندما تكون المطابقة ملتبسة، مثل وجود متجرين متقاربين لهما اسمان متشابهان، ويختار أحد المشغّلين الإدراج الصحيح من إدراجات الأنشطة التجارية التابعة للحساب.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.locationIdbodyنعممعرّف الموقع المرمّز باستخدام base64.
input.connectedAccountIdbodyنعممعرّف UUID للحساب الذي يملك إدراج النشاط التجاري.
input.connectedAccountListingIdbodyنعمقيمة id لسجل من نقطة نهاية إدراجات الأنشطة التجارية التابعة للحساب. وليست listingId.
Connect listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'
JSON
{  "data": {    "connectListing": {      "success": true,      "message": null    }  }}

عند فشل الربط، تُرجع نقطة النهاية success: false مع قيمة message غير null، مثل Listing record not found عندما لا يُعثر على إدراج النشاط التجاري بالمعرّف المحدد، أو ملاحظة تفيد بأن إدراج النشاط التجاري متصل بالفعل بموقع آخر. في كلتا حزمتَي SDK، تتبع هذه الدالة مورد listings، وليس الحسابات المتصلة.

فصل إدراج نشاط تجاري واحد عن موقع

POST /connected-accounts/disconnect-listing

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

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.locationIdbodyنعممعرّف الموقع الواحد المرمّز باستخدام base64.
input.sitebodyأحد الخياراتGOOGLE أو FACEBOOK أو APPLE. مطلوب ما لم يُرسل providerId.
input.providerIdbodyأحد الخياراتمعرّف الحساب الخاص بمنصة النشر، بدلًا من site.
Disconnect listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "site": "GOOGLE" } }'
JSON
{  "data": {    "disconnectConnectedAccountsLocations": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

يؤدي عدم إرسال أيٍّ من site وproviderId إلى إرجاع SY10056. إذا لم يكن للموقع اتصال نشط بتلك المنصة، فستُرجع نقطة النهاية SY10057 بدلًا من الإبلاغ عن نجاح دون إجراء، لذا فإن success: true تعني فعلًا إزالة رابط. تقبل حزم SDK المعامِل site فقط وتحوّل قيمته إلى أحرف كبيرة.

إنشاء موقع من إدراج نشاط تجاري

POST /connected-accounts/create-location-from-listing

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

عند الاستيراد من Google، لا تُعاد إرسال البيانات إلى Google، لذا تظل حالة إدراج النشاط التجاري فيه IN_PROGRESS إلى أن يُنشر أول تحديث للموقع على ذلك الإدراج. تُرسل البيانات إلى كل منصة نشر أخرى كالمعتاد، ولا تقبل نقطة النهاية هذه تحديد نطاق المواقع، لذا يُنشأ الموقع لجميع منصات النشر المرتبطة بحسابك. قلّص هذا النطاق باستخدام enabledSiteIds مباشرة بعد الإنشاء، وأرسل هذا التحديث فورًا: تُنشأ بنود الطلب لمنصات النشر الأخرى بعد الإنشاء بوقت قصير، ولا يسحب التحديث أي بنود أُنشئت بالفعل.

لا توفر أي من حزمتَي SDK دالة لاستدعاء نقطة النهاية هذه حتى الآن، لذا تستدعي أمثلة Python وNode واجهة REST باستخدام الترويسة نفسها.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.connectedAccountIdbodyنعمUUID للحساب الذي يملك إدراج النشاط التجاري.
input.connectedAccountListingIdbodyنعمقيمة id لسجل من نقطة نهاية إدراجات الأنشطة التجارية للحساب. وليست listingId.
Create from listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/create-location-from-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'
JSON
{  "data": {    "createLocationFromConnectedAccountListing": {      "success": true,      "locationId": 88277,      "errors": null    }  }}

locationId هو databaseId العادي للموقع الجديد. عند الفشل، تكون قيمة success هي false، وقيمة locationId هي null، ويحمل errors رمزًا يوضح السبب مثل SY81067 (لم يُعثر على إدراج النشاط التجاري باستخدام المعرّف)؛ ومن الأسباب الأخرى أن يكون إدراج النشاط التجاري مرتبطًا بالفعل بموقع آخر، أو أن تكون بيانات اعتماد الحساب قد انتهت صلاحيتها. بعد إنشاء الموقع، أدِره كأي موقع آخر.

عرض مجلدات حساب Google

GET /connected-accounts/{connectedAccountId}/folders

تُرجع مجموعات حسابات Google Business Profile (المجلدات) التي يمكن لحساب Google المتصل الوصول إليها. استخدمها قبل إنشاء إدراج نشاط تجاري على GMB لضمان وضع الملف التجاري الجديد في المجموعة التي يتوقعها المالك. تأتي الاستجابة في صورة مصفوفة عادية ضمن getFoldersUnderGoogleAccount، وليست صفحة نتائج. المسار صالح فقط لاتصالات GoogleAccount.

الاسمالموضعمطلوبملاحظات
connectedAccountIdpathنعمUUID لحساب من نوع Google.
Folders
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/folders \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "getFoldersUnderGoogleAccount": [      { "folderId": "accounts/104890024806530350198", "folderName": "Bright Smile Dental", "locationCount": null }    ]  }}

استخدم folderId دون تغيير؛ فهو السلسلة النصية accounts/{id}، وليس رقمًا. قد تكون قيمة locationCount هي null عندما لا يوفرها Google، لذا تعامل معها على أنها اختيارية.

إنشاء Google Business Profile لموقع

POST /locations/create/gmb-listing

تُنشئ إدراج نشاط تجاري جديدًا تمامًا على Google لموقع ليس له إدراج، ضمن حساب Google متصل، ويمكن اختياريًا وضعه داخل مجلد. تختلف هذه العملية عن connect-listing، التي تربط إدراج نشاط تجاري موجودًا بالفعل. يجب أن يتضمن الموقع اسمًا وعنوانًا ورقم هاتف مسبقًا، ولا يمكن أن يكون لكل موقع سوى إدراج نشاط تجاري واحد على Google.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.locationIdbodyنعممعرّف الموقع بترميز Base64.
input.connectedAccountIdbodyنعمUUID لحساب Google الذي سيُنشأ إدراج النشاط التجاري ضمنه.
input.folderIdbodyلاالسلسلة النصية accounts/{id} من نقطة نهاية المجلدات. احذفها للإنشاء في جذر الحساب.
Create GMB listing
curl -X POST https://listingsapi.com/api/v4/locations/create/gmb-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "folderId": "accounts/104890024806530350198"  }}'
JSON
{  "data": {    "createGmbListingForLocation": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

الإنشاء غير متزامن: تعني success: true أن الطلب قد قُبل، ويراجع Google الملفات التجارية الجديدة قبل نشرها. عندما تكون قيمة success هي false، يوضح errors السبب: غياب حقول مطلوبة، أو وجود إدراج نشاط تجاري على Google بالفعل، أو كون الموقع مؤرشفًا، أو كون الحساب غير نشط.

قطع اتصال حساب Google بالكامل

POST /connected-accounts/disconnect-google

يقطع الاتصال للحساب بالكامل: تتوقف مزامنة كل موقع مرتبط من خلاله. لا يوجد حقل locationIds؛ لفصل موقع واحد والإبقاء على الحساب، استخدم disconnect-listing بدلًا من ذلك. استخدم هذه العملية عند مغادرة عميل، أو عندما يتعذر إلغاء تفويض معطّل وتريد البدء من جديد برابط اتصال جديد.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.connectedAccountIdbodyنعممعرّف UUID لحساب Google. يُقطع اتصال الحساب بالكامل.
Disconnect Google
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-google \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d" } }'
JSON
{  "data": {    "gmbBulkDisconnect": {      "success": true    }  }}

تُعاد success: true حتى عندما يكون connectedAccountId غير معروف، لذا فهي تعني «تمت معالجة الطلب»، ولا تعني «تمت إزالة اتصال نشط». اعرض قائمة الحسابات المتصلة مرة أخرى إذا كنت بحاجة إلى التأكد.

قطع اتصال حساب Facebook بالكامل

POST /connected-accounts/disconnect-facebook

العملية المقابلة في Facebook، وتستخدم جسم الطلب نفسه. تتوقف مزامنة الصفحات المرتبطة من خلال الحساب، وتتوقف تفاعلات Facebook عن الظهور.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.connectedAccountIdbodyنعممعرّف UUID لحساب Facebook. يُقطع اتصال الحساب بالكامل.
Disconnect Facebook
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-facebook \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d" } }'
JSON
{  "data": {    "fbBulkDisconnect": {      "success": true    }  }}

مفتاح الاستجابة هو fbBulkDisconnect. كما في Google، فإن success: true عند استخدام id غير معروف تعني أن الطلب قد عولج، لا أن الاتصال قد أُزيل.

قطع اتصال موقع واحد بمنصة نشر

POST /locations/oauth-disconnect

جزء قطع الاتصال من سير عمل OAuth الخاص بكل موقع. إنها العملية نفسها التي تنفذها disconnect-listing، لكنها متاحة عبر مسار ثانٍ: جسم طلب input مطابق ومفتاح الاستجابة disconnectConnectedAccountsLocations نفسه. اختر المسار الأوضح في التكامل الذي تنفذه.

الاسمالموضعمطلوبملاحظات
inputbodyنعمكائن حاوٍ.
input.locationIdbodyنعممعرّف الموقع الواحد بترميز Base64.
input.sitebodyأحد الخياراتGOOGLE أو FACEBOOK أو APPLE. مطلوب ما لم يُرسل providerId.
input.providerIdbodyأحد الخياراتمعرّف الحساب لدى منصة النشر نفسها، بدلًا من site.
OAuth disconnect
curl -X POST https://listingsapi.com/api/v4/locations/oauth-disconnect \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "site": "GOOGLE" } }'
JSON
{  "data": {    "disconnectConnectedAccountsLocations": {      "clientMutationId": null,      "success": true,      "errors": null    }  }}

تنطبق قواعد SY10056 وSY10057 نفسها، ويتلقى الطلب الذي يستخدم مفتاحًا غير مخوّل بالوصول إلى هذا الموقع استجابة 403 مع SY90003. يُبقي قطع الاتصال الموقع وبياناته كما هي؛ وتتوقف فقط المزامنة الصادرة إلى منصة النشر تلك. وجّه المالك مجددًا إلى عنوان URL للاتصال، أو نفّذ المطابقة وconnect-listing، لربط إدراج النشاط التجاري الصحيح بعد ذلك.

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

تؤدي الطلبات ذات البنية غير الصحيحة والمفاتيح غير الصالحة إلى إرجاع حالة 4xx مع errors[] في المستوى الأعلى، ويبدأ message الخاص به برمز الخطأ. قد تُرجع عمليات الكتابة أيضًا حالة 200 مع success: false والسبب داخل data.<operation>، لذا افحص جسم الاستجابة لكل عملية كتابة. تتوفر القائمة الكاملة في رموز الأخطاء.

الرمز أو الحالةالمعنىالحل
SY90016 (400)استُخدم مفتاح Read مع POST.استخدم مفتاح Write.
SY90003 (403)المفتاح غير مخوّل بتوصيل هذا الموقع أو قطع اتصاله.استخدم مفتاحًا لديه صلاحية الوصول إلى الموقع.
SY10056 (200)لم يُرسل طلب قطع الاتصال أيًا من site أو providerId.أرسل أحدهما.
SY10057 (200)لا يوجد اتصال نشط للموقع بخدمة النشر تلك.لا يوجد ما يمكن إزالته؛ تحقّق من إدراجات النشاط التجاري الخاصة بالموقع.
SY81067 (200)تعذّر العثور على ما يشير إليه connectedAccountListingId في create-from-listing.اجلب إدراجات النشاط التجاري للحساب مجددًا واستخدم id من أحد السجلات.
400, Variable "$input" ... was not providedلم يُوضَع جسم الطلب داخل input، أو كان أحد الحقول المطلوبة مفقودًا.ضع جسم الطلب داخل input؛ واستخدم connectedAccountListingId، وليس listingId.
400، قيمة enum غير صالحةأُعيد استخدام حالة CONNECTED الخاصة بأحد السجلات بوصفها قيمة مرشّح القائمة status.رشّح باستخدام Connected أو NotConnected أو ConnectionIssue.
429تم تجاوز حد معدل الطلبات.انتظر وفقًا لـ Retry-After؛ راجع حدود معدل الطلبات.

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