تتيح واجهة Google Health API لتطبيقك تلقّي إشعارات في الوقت الفعلي عند تغيير بيانات المستخدم الصحية. بدلاً من إجراء استطلاع للتغييرات، يتلقّى خادمك ويب هوك لطلب HTTPS POST فور توفّر البيانات في Google Health API.
أنواع البيانات المتوافقة
تتوفّر إشعارات الويب هوك لأنواع البيانات التالية:
| نوع البيانات | العمليات المتاحة |
النطاق |
|---|---|---|
|
الدقائق النشطة
dataType:
active-minutesfilter parameter: active_minutes
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
دقائق نطاق النشاط
dataType:
active-zone-minutesfilter parameter: active_zone_minutes
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
مستوى النشاط
|
قائمة، تسوية | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
Altitude
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
الغلوكوز في الدم
|
list, get, reconcile, rollup, dailyRollup | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
نسبة الدهون بالجسم
dataType:
body-fatfilter parameter: body_fat
نوع السجلّ: نموذج
الأجهزة المتوافقة
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
السعرات الحرارية المحروقة في نطاق معدّل نبضات القلب
dataType:
calories-in-heart-rate-zonefilter parameter: calories_in_heart_rate_zone
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
|
rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
تغيُّر معدّل نبضات القلب اليومي
dataType:
daily-heart-rate-variabilityfilter parameter: daily_heart_rate_variability
نوع السجلّ: يومي
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
نطاقات معدّل نبضات القلب اليومية
dataType:
daily-heart-rate-zonesfilter parameter: daily_heart_rate_zones
نوع السجلّ: يومي
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
نسبة الأكسجين في الدم يوميًا
dataType:
daily-oxygen-saturationfilter parameter: daily_oxygen_saturation
نوع السجلّ: يومي
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
معدّل التنفس اليومي
dataType:
daily-respiratory-ratefilter parameter: daily_respiratory_rate
نوع السجلّ: يومي
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
معدّل النبض اليومي أثناء الراحة
dataType:
daily-resting-heart-ratefilter parameter: daily_resting_heart_rate
نوع السجلّ: يومي
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
استنتاجات درجة الحرارة اليومية أثناء النوم
dataType:
daily-sleep-temperature-derivationsfilter parameter: daily_sleep_temperature_derivations
نوع السجلّ: يومي
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
المسافة
dataType:
distancefilter parameter: distance
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
التمارين الرياضية
dataType:
exercisefilter parameter: exercise
نوع التسجيل: جلسة
الأجهزة المتوافقة
|
list, get, reconcile, create, update, batchDelete | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
الطوابق
|
reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
معدّل نبضات القلب
dataType:
heart-ratefilter parameter: heart_rate
نوع السجلّ: نموذج
دقة التخزين: ثانية واحدة
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
تغيُّر معدّل نبضات القلب
dataType:
heart-rate-variabilityfilter parameter: heart_rate_variability
نوع السجلّ: نموذج
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
الارتفاع
|
list, get, reconcile, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
سجلّ شرب الماء
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .nutrition.readonly.nutrition.writeonly |
|
سجلّ التغذية
dataType:
nutrition-logfilter parameter: nutrition_log
نوع التسجيل: جلسة
الأجهزة المتوافقة
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .nutrition.readonly.nutrition.writeonly |
|
ملخّص جودة ومدة النوم استنادًا إلى معدّل التنفس
dataType:
respiratory-rate-sleep-summaryfilter parameter: respiratory_rate_sleep_summary
نوع السجلّ: نموذج
الأجهزة المتوافقة
|
قائمة، تسوية | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
الجري والحد الأقصى لاستهلاك الأكسجين
dataType:
run-vo2-maxfilter parameter: run_vo2_max
نوع السجلّ: نموذج
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
فترة الخمول
dataType:
sedentary-periodfilter parameter: sedentary_period
نوع السجلّ: Interval
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
النوم
dataType:
sleepfilter parameter: sleep
نوع التسجيل: جلسة
الأجهزة المتوافقة
|
list, get, reconcile, create, update, batchDelete | .sleep.readonly.sleep.writeonly |
|
الخطوات
dataType:
stepsfilter parameter: steps
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
الأجهزة المتوافقة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
الوقت في نطاق معدّل نبضات القلب
dataType:
time-in-heart-rate-zonefilter parameter: time_in_heart_rate_zone
نوع السجلّ: Interval
دقة التخزين: دقيقة واحدة
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
الوزن
dataType:
weightfilter parameter: weight
نوع السجلّ: نموذج
الأجهزة المتوافقة
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
نطاقات الإشعارات
يتم إرسال الإشعارات لأنواع البيانات هذه فقط عندما يمنح المستخدم موافقته على أحد النطاقات المقابلة:
- النشاط: يشمل أنواع بيانات الدقائق النشطة والخطوات والارتفاع والمسافة والطوابق:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonlyhttps://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly
- المقاييس الصحية، والتي تشمل نوع بيانات الوزن:
https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonlyhttps://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.writeonly
- النوم، ويشمل نوع بيانات النوم:
https://www.googleapis.com/auth/googlehealth.sleep.readonlyhttps://www.googleapis.com/auth/googlehealth.sleep.writeonly
حسابات خدمة "إدارة الهوية وإمكانية الوصول"
على الرغم من أنّ ذلك ليس مطلوبًا، ننصح باستخدام حساب خدمة على "إدارة الهوية وإمكانية الوصول" عند ضبط المشتركين في Google Health API. توفّر حسابات الخدمة أمانًا أفضل لأعباء عمل التطبيقات مقارنةً بحسابات المستخدمين العادية من خلال الميزات التالية:
- بيانات الاعتماد الآلية القصيرة الأجل: عند ربط حسابات الخدمة ببيئة تنفيذ على Google Cloud (مثل Compute Engine أو Cloud Run أو Google Kubernetes Engine)، تحصل هذه الحسابات تلقائيًا على بيانات اعتماد آمنة وقصيرة الأجل وتغيّرها بشكل دوري. ويؤدي ذلك إلى إزالة مخاطر إدارة وتخزين المفاتيح الثابتة الدائمة.
- مبدأ الحدّ الأدنى من الأذونات المميّزة: توفّر حسابات الخدمة هويات مخصّصة لأعباء العمل. يمكنك منحهم فقط الأذونات المحدّدة اللازمة لإدارة نقاط نهاية المشتركين، ما يمنعهم من الوصول إلى موارد Google Cloud الأخرى.
- استقلالية مراحل النشاط: تعمل حسابات الخدمة بشكل مستقل عن حساب أي مستخدم فردي، ما يضمن عدم تأثّر استقرار المصادقة على المدى الطويل بالتغييرات في الموظفين.
إعداد حساب خدمة
لضبط تطبيق المشترك للمصادقة باستخدام حساب خدمة:
- إنشاء حساب خدمة: في وحدة تحكُّم Google Cloud، انتقِل إلى صفحة "إدارة الهوية وإمكانية الوصول والمشرف " في مشروعك من أجل إنشاء حساب خدمة جديد يديره المستخدم.
- منح الأدوار اللازمة في "إدارة الهوية وإمكانية الوصول" (IAM): امنح حساب الخدمة الأدوار المناسبة المطلوبة لإدارة المشتركين في مشروع على السحابة الإلكترونية على Google Cloud.
- ربط حساب الخدمة بعبء العمل: اضبط البيئة التي تستضيف منطق المشترك ليتم تشغيلها كحساب الخدمة الجديد.
يتيح ذلك للرمز البرمجي للتطبيق (مثل مكتبات عملاء Google API)
رصد بيانات الاعتماد قصيرة الأجل لحساب الخدمة واستخدامها تلقائيًا
عند طلب البيانات من واجهة برمجة التطبيقات
projects.subscribersREST API.
أدوار CPE
لإدارة المشتركين أو الاشتراكات في Google Health API، يجب منح الدور المناسب لحساب الخدمة الذي ينتحل الهوية ويُجري طلبات البيانات من واجهة برمجة التطبيقات. بناءً على مستوى الوصول المطلوب، يمكنك إسناد أحد الأدوار التالية:
- Google Health API Read
- محرِّر Google Health API
- مشرف Google Health API
مزيد من المعلومات حول أدوار وأذونات إدارة الهوية وإمكانية الوصول في Google Health API
إدارة المشتركين
قبل أن تتمكّن من تلقّي الإشعارات، عليك تسجيل "مشترك" يمثّل نقطة نهاية الإشعارات في تطبيقك. يمكنك إدارة المشتركين
باستخدام REST API المتاحة على
projects.subscribers.
يجب أن تستخدم نقطة نهاية المشترك بروتوكول HTTPS (TLSv1.2+) وأن تكون متاحة للجميع.
أثناء إنشاء المشتركين وتعديلهم، تُجري Google Health API
تحدّيًا للتحقّق من ملكيتك لمعرّف الموارد المنتظم (URI) لنقطة النهاية. وفي حال تعذّر إثبات الملكية، لن تنجح عمليات إنشاء المشتركين وتعديلهم، وسيظهر الخطأ FailedPreconditionException.
إنشاء مشترك
لتسجيل مشترك جديد في مشروعك، استخدِم نقطة النهاية
create. يجب تقديم ما يلي:
-
project-id: رقم المشروع الذي تم إنشاء حساب خدمة الويب هوك فيه subscriberId: معرّف فريد تقدّمه للمشترك. يجب أن يتراوح طول هذا المعرّف بين 4 و36 حرفًا، وأن يتطابق مع التعبير العادي ([a-z]([a-z0-9-]{2,34}[a-z0-9])).-
endpointUri: عنوان URL المقصود لإشعارات الويب هوك. subscriberConfigs: أنواع البيانات التي تريد تلقّي إشعارات بشأنها، وسياسة الاشتراك لكل منها.-
endpointAuthorization: آلية التفويض لنقطة النهاية ويجب أن يحتوي علىsecretتقدّمه أنت. يتم إرسال قيمةsecretفي عنوانAuthorizationمع كل رسالة إشعار. يمكنك استخدام هذا الرمز للتحقّق من أنّ الطلبات الواردة هي من Google Health API. على سبيل المثال، يمكنك ضبطsecretعلىBearer R4nd0m5tr1ng123لمصادقة Bearer، أوBasic dXNlcjpwYXNzd29yZA==للمصادقة الأساسية.
في subscriberConfigs، عليك ضبط subscriptionCreatePolicy لكل نوع بيانات. اضبطها على AUTOMATIC لاستخدام الاشتراكات التلقائية، أو MANUAL إذا كنت
تنوي إدارة اشتراكات المستخدمين بنفسك. يمكنك الاطّلاع على الاشتراكات التلقائية والاشتراكات اليدوية لمزيد من التفاصيل حول كل خيار.
طلب
POST https://health.googleapis.com/v4/projects/project-id/subscribers?subscriberId=subscriber-id
{
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
],
"endpointAuthorization": {
"secret": "Bearer example-secret-token"
}
}الردّ
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
]
}عرض قائمة المشتركين
استخدِم نقطة النهاية list
لاسترداد جميع المشتركين المسجَّلين في مشروعك.
طلب
GET https://health.googleapis.com/v4/projects/project-id/subscribers
الردّ
{
"subscribers": [
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
],
"endpointAuthorization": {
"authorizationTokenSet": true
}
}
],
"totalSize": 1
}تعديل مشترك
استخدِم نقطة النهاية patch لتعديل مشترك في مشروعك. الحقول التي يمكن تعديلها هي
endpointUri وsubscriberConfigs وendpointAuthorization.
يمكنك تعديل الحقول من خلال تقديم مَعلمة طلب البحث updateMask ونص الطلب. يجب أن يحتوي updateMask على قائمة قيم مفصولة بفاصلة لأسماء الحقول التي تريد تعديلها، باستخدام تنسيق Camel Case لأسماء الحقول (على سبيل المثال، endpointUri). يجب أن يحتوي نص الطلب على عنصر Subscriber جزئي يتضمّن القيم الجديدة للحقول التي تريد تعديلها. يتم تعديل الحقول المحدّدة في updateMask فقط. إذا قدّمت حقولاً في نص الطلب غير مضمّنة في updateMask، سيتم تجاهلها.
في حال تعديل endpointUri أو endpointAuthorization، يتم التحقّق من نقطة النهاية. يُرجى الاطّلاع على التحقّق من نقطة النهاية لمعرفة التفاصيل.
عند تعديل subscriberConfigs، يُرجى العِلم أنّه سيتم استبدال الملف بالكامل، وليس دمجه. إذا تم تضمين subscriberConfigs في updateMask، يتم استبدال جميع الإعدادات المخزَّنة لهذا المشترك بالقائمة المقدَّمة في نص الطلب. لإضافة إعداد أو إزالته، يجب تقديم المجموعة الكاملة من
الإعدادات. إذا كنت تعدّل حقولاً أخرى وتريد الاحتفاظ بإعداداتك الحالية، يمكنك حذف subscriberConfigs من updateMask.
طلب
PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id?updateMask=endpointUri
{
"endpointUri": "https://myapp.com/new-webhooks/health"
}الردّ
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/new-webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
]
}حذف مشترك
استخدِم نقطة النهاية delete لإزالة مشترك من مشروعك. بعد الحذف، لن يتلقّى المشترك
أي إشعارات بعد ذلك.
طلب
DELETE https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
الردّ
يتم عرض نص استجابة فارغ مع حالة HTTP `200 OK` إذا تم الحذف بنجاح.{}التحقُّق من نقطة النهاية
لضمان أمان وموثوقية تسليم الإشعارات، تُجري واجهة Google Health API عملية مصافحة إلزامية للتحقّق بخطوتين عند إنشاء مشترك أو تعديل إعدادات نقطة النهاية (endpointUri أو endpointAuthorization). يتم تنفيذ هذه العملية بشكل متزامن أثناء طلب البيانات من واجهة برمجة التطبيقات. ترسل الخدمة طلبَي POST آليَّين إلى معرّف الموارد المنتظم (URI) لنقطة النهاية،
باستخدام وكيل المستخدم Google-Health-API-Webhooks، مع نص JSON
{"type": "verification"}.
- المصافحة المصرَّح بها: يتم إرسال الطلب الأول مع عنوان
Authorizationالذي تم ضبطه. يجب أن يستجيب الخادم بالحالة200 OKأو201 Created. - تحدّي غير مصرّح به: يتم إرسال الطلب الثاني بدون بيانات اعتماد.
يجب أن يستجيب الخادم بالحالة
401 Unauthorizedأو403 Forbidden.
تؤكّد هذه المصافحة أنّ نقطة النهاية نشطة وتفرض الأمان بشكل صحيح. إذا تعذّر تنفيذ أي من الخطوتين، سيتعذّر طلب البيانات من واجهة برمجة التطبيقات مع ظهور الخطأ FAILED_PRECONDITION. بعد نجاح عملية الاتصال هذه، يتم حفظ المشترك وتفعيله لتلقّي إشعارات البيانات الصحية.
تدوير المفاتيح
إذا كنت بحاجة إلى تدوير مفاتيح endpointAuthorization، اتّبِع الخطوات التالية:
- اضبط نقطة النهاية لقبول قيم
endpointAuthorizationالقديمة والجديدة. - عدِّل إعدادات المشترك باستخدام قيمة
endpointAuthorizationالجديدة باستخدام طلبpatchمع?updateMask=endpointAuthorization. - اضبط نقطة النهاية لقبول قيمة
endpointAuthorizationالجديدة فقط بعد التأكّد من نجاح الخطوة 2.
اشتراكات المستخدمين
تساعدك واجهة Google Health API في إدارة اشتراكات المستخدمين بكفاءة، ما يقلل من الحاجة إلى التسجيل اليدوي أثناء عملية إعداد المستخدمين.
الاشتراكات التلقائية
ننصح باستخدام الاشتراكات التلقائية. لتفعيل هذه الميزة، اضبط
subscriptionCreatePolicy على AUTOMATIC في subscriberConfigs لأنواع
البيانات المحدّدة. إنّ dataTypes التي تحدّدها باستخدام سياسة AUTOMATIC هي أنواع البيانات نفسها التي ترسل Google Health API إشعارات بشأنها، شرط أن يمنح المستخدم موافقته على أنواع البيانات هذه أيضًا.
عندما يمنح المستخدم موافقة للتطبيق على النطاقات التي تتوافق مع أنواع البيانات
التي تتضمّن سياسة AUTOMATIC، تتتبّع Google Health API تلقائيًا
وترسل إشعارات لأنواع البيانات الناتجة عن التقاطع
بين أنواع البيانات التي وافق عليها المستخدم وأنواع بيانات ضبط المشتركين التلقائية
لهذا المستخدم. بعد ذلك، يتم إرسال الإشعارات إلى نقطة النهاية
كلما أنشأ هذا المستخدم بيانات جديدة لهذه الأنواع. ينطبق ذلك على المستخدمين الذين يمنحون الموافقة قبل إنشاء المشترك أو بعده. لا يتم ملء الإشعارات السابقة للبيانات التي تم إنشاؤها قبل إنشاء المشترك.
إذا ألغى المستخدم موافقته، ستتوقف الإشعارات الخاصة بأنواع البيانات ذات الصلة. تتم إدارة الاشتراكات التلقائية من قِبل Google ولا يمكن إدراجها أو حذفها بشكل فردي، بل تتم إزالتها فقط عند حذف المشترك الرئيسي.
الاشتراكات اليدوية
إذا تم ضبط المشترك على "يدوي" subscription_create_policy
لأنواع بيانات معيّنة، يجب إنشاء الاشتراكات وإدارتها بشكل صريح
لكل مستخدم. يربط الاشتراك مستخدمًا معيّنًا بنقطة نهاية المشترك
لمجموعة محدّدة من أنواع البيانات. يمكن للمطوّرين استخدام واجهات برمجة تطبيقات محدّدة لإجراء ما يلي:
- إنشاء اشتراكات (يدوية) لكل
healthUserId: يؤدي هذا الإجراء إلى إنشاء اشتراك جديد لمستخدم معيّن. تتطلّب هذه الطريقة أن يكون لدى المشتركSubscriptionCreatePolicyمضبوطًا علىMANUALلأنواع البيانات المطلوبة. - تعديل الاشتراك (يدويًا): لتعديل أنواع البيانات لاشتراك مستخدم حالي
- حذف الاشتراك (يدويًا): يحذف اشتراك مستخدم معيّن. بعد الحذف، لن تتلقّى نقطة نهاية المشترك إشعارات لهذا المستخدم لأنواع البيانات المرتبطة.
- List (manual) subscriptions - Lists all active subscriptions for a given subscriber. يمكنك فلترة النتائج حسب المستخدم أو نوع البيانات.
الإشعارات
عندما تتغيّر بيانات مستخدم لنوع بيانات مشترك، ترسل Google Health API طلب HTTPS POST إلى عنوان URL لنقطة نهاية المشترك.
تنسيق الإشعار
تحتوي حمولة الإشعار على تفاصيل حول تغيير البيانات، بما في ذلك رقم تعريف المستخدم ونوع البيانات والفواصل الزمنية، والتي يمكنك استخدامها لطلب البيانات المعدَّلة. عند حدوث تعديلات متعددة أو تجميع التعديلات، يتم تجميع الإشعارات معًا وإرسالها كمصفوفة JSON لعناصر الإشعارات.
عندما يتم تفعيل إشعار الويب هوك، ترسل Google Health API طلب HTTPS POST إلى نقطة نهاية المشترك بالتنسيق التالي:
إدراج أو تعديل (بيانات السلسلة الزمنية)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-08T01:29:00Z",
"endTime": "2026-03-08T01:34:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 29
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 34
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T17:29:00",
"endTime": "2026-03-07T17:34:00"
}
}
]
}
}حذف (بيانات السلسلة الزمنية)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
[
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "DELETE",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T12:00:00Z",
"endTime": "2026-08-12T12:30:00Z"
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T12:00:00",
"endTime": "2026-08-12T12:30:00"
}
}
]
}
}
]حذف (البيانات التي يمكن تحديد هوية صاحبها)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "DELETE",
"dataType": "sleep",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T22:00:00Z",
"endTime": "2026-08-13T06:00:00Z"
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T22:00:00",
"endTime": "2026-08-13T06:00:00"
}
}
],
"recordId": "9875412"
}
}مجمّعة (تعدُّد المستخدمين وأنواع بيانات)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
[
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "health-user-id-1",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-08T01:29:00Z",
"endTime": "2026-03-08T01:34:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 29
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 34
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T17:29:00",
"endTime": "2026-03-07T17:34:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_WEIGHT",
"healthUserId": "health-user-id-1",
"operation": "UPSERT",
"dataType": "weight",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-07T15:14:00Z",
"endTime": "2026-03-07T15:16:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 7,
"minutes": 14
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 7,
"minutes": 16
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T07:14:00",
"endTime": "2026-03-07T07:16:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "health-user-id-2",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 20
},
"time": {
"hours": 0,
"minutes": 0
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 21
},
"time": {
"hours": 0,
"minutes": 0
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-20T00:00:00",
"endTime": "2026-08-21T00:00:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id-2",
"operation": "UPSERT",
"dataType": "sleep",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T22:00:00Z",
"endTime": "2026-08-13T06:00:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 12
},
"time": {
"hours": 22,
"minutes": 0
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 13
},
"time": {
"hours": 6,
"minutes": 0
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T22:00:00",
"endTime": "2026-08-13T06:00:00"
}
}
],
"recordId": "9875412"
}
}
]يشير الحقل operation إلى نوع التغيير الذي أدّى إلى ظهور الإشعار:
-
UPSERT: يتم إرسالها عند إضافة أي بيانات أو تعديلها. -
DELETE: يتم إرسال هذا الإشعار عندما يحذف المستخدم البيانات بشكل صريح (مثل حذفdataPointsباستخدام تطبيق Fitbit أو إجراء حذف مجمّع باستخدام واجهة برمجة التطبيقات). لا يتم إرسال إشعارات الويب هوك لأحداث الحذف على مستوى النظام، مثل إبطال المستخدم لأذونات التطبيق أو حذف حسابه على Fitbit.
ننصحك بجعل منطق معالجة الإشعارات متكررًا، خاصةً لعمليات UPSERT، لأنّ عمليات إعادة المحاولة يمكن أن تؤدي إلى إرسال إشعارات مكرّرة.
حقل clientProvidedSubscriptionName هو معرّف فريد:
- بالنسبة إلى الاشتراكات التي تتضمّن سياسة
MANUAL، يحتوي هذا الحقل على اسم الاشتراك الثابت الذي يقدّمه المطوّر والمحدّد عند إنشاء الاشتراك. يوفّر ذلك معرّفًا ثابتًا لإدارة الاشتراكات اليدوية. - بالنسبة إلى الاشتراكات التي تم إنشاؤها باستخدام سياسة
AUTOMATIC، تنشئ Google Health API معرّفًا تلقائيًا وتخصّصه بالتنسيق:auto-<project-number>-<subscriber-id>-<WEBHOOK_DATA_TYPE_TOKEN>، حيث:-
<project-number>هو رقم مشروع المطوّر على Google Cloud (على سبيل المثال،362978535920). -
<subscriber-id>هو معرّف تسجيل المشترك أو اسم المشترك (على سبيل المثال،google-health-sync). -
<WEBHOOK_DATA_TYPE_TOKEN>هو الرمز المميّز الذي يمثّل نوع البيانات المحدّد. يمكنك الاطّلاع على مفردات رموز أنواع بيانات الويب هوك لمعرفة جميع الرموز الممكنة.
-
يضمن تضمين clientProvidedSubscriptionName لكل من السياسات اليدوية والتلقائية تنسيقًا متسقًا لحمولة الإشعارات في جميع أنواع الاشتراكات.
ربط أرقام تعريف المستخدمين
healthUserId هو معرّف Google Health API للمستخدم الذي
تغيّرت بياناته. إذا كان تطبيقك يتيح استخدام تعدُّد المستخدمين، يمكنك تلقّي
إشعارات لأي مستخدم منح تطبيقك الموافقة. عند تلقّي إشعار، استخدِم healthUserId لتحديد المستخدم الذي تم تغيير بياناته، حتى تتمكّن من استخدام بيانات اعتماد OAuth الخاصة به لطلب بياناته.
لربط بيانات اعتماد OAuth الخاصة بالمستخدم بحساب healthUserId، استخدِم نقطة النهاية getIdentity. يمكنك استدعاء نقطة النهاية هذه باستخدام بيانات اعتماد المستخدم أثناء عملية الإعداد لاسترداد healthUserId وتخزين عملية الربط هذه. لا يتغيّر هذا الربط بمرور الوقت، لذا يمكن تخزينه مؤقتًا إلى أجل غير مسمى. للاطّلاع على مثال، يُرجى مراجعة الحصول على رقم تعريف المستخدم. يتيح لك ذلك اختيار بيانات اعتماد المستخدم الصحيحة عند طلب البيانات استنادًا إلى healthUserId في الإشعار.
الفترات الزمنية
تحتوي مصفوفة intervals على عنصر واحد أو أكثر يمثّل الفواصل الزمنية للبيانات المعدَّلة:
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
physicalTimeInterval |
object |
لا | الفاصل الزمني الفعلي للبيانات المعدَّلة بالتوقيت العالمي المنسق (بتنسيق YYYY-MM-DDTHH:MM:SSZ) يتم ملء هذا الحقل للمقاييس خلال اليوم، ويتم حذفه لعمليات التجميع اليومية والأنشطة التي تستغرق يومًا كاملاً. |
civilDateTimeInterval |
object |
نعم | تمثّل هذه السمة تاريخ التقويم المدني (المحلي) والفاصل الزمني للبيانات المعدَّلة، بدون معادلات التوقيت العالمي المنسَّق أو المنطقة الزمنية. |
civilIso8601TimeInterval |
object |
نعم | تمثّل هذه السمة الفاصل الزمني المدني (المحلي) كسلسلة ISO 8601 (بتنسيق YYYY-MM-DDTHH:MM:SS) بدون فروق التوقيت العالمي المنسَّق أو المنطقة الزمنية. |
بالنسبة إلى الأنشطة التي تستغرق يومًا كاملاً والإحصاءات المجمّعة اليومية، يتم حذف الحقل physicalTimeInterval عمدًا من حمولة الإشعار. ويعود السبب في ذلك إلى أنّ الأحداث التي تستمر طوال اليوم يتم تجميعها حسب تاريخها المدني الاسمي، ويمكن أن تكون المدد الزمنية الفعلية غير دقيقة عند عبور المناطق الزمنية. عند معالجة الأحداث التي تستمر طوال اليوم،
يجب الاعتماد على الحقلين civilDateTimeInterval أو
civilIso8601TimeInterval كأفضل ممارسة. للحصول على تفاصيل حول كيفية الاستعلام عن نقاط البيانات هذه باستخدام فلاتر الوقت المدني، يُرجى الاطّلاع على فلترة البيانات حسب وقت البدء المدني للفترة الزمنية.
في ما يلي مثال على حمولة إشعار لنشاط يستغرق يومًا كاملاً، حيث تم حذف الحقل physicalTimeInterval:
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-503461148219-lindasubscriber-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "343864966078399341",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 7,
"day": 14
},
"time": {}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 7,
"day": 15
},
"time": {}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-07-14T00:00:00",
"endTime": "2026-07-15T00:00:00"
}
}
]
}
}مفردات رموز أنواع بيانات الويب هوك
عند استخدام سياسة AUTOMATIC، يحتوي clientProvidedSubscriptionName الذي تم إنشاؤه على أحد رموز اللاحقة WEBHOOK_DATA_TYPE_* التالية المكتوبة بأحرف لاتينية كبيرة، وذلك حسب نوع البيانات:
| رمز مميّز لنوع بيانات الويب هوك | نوع البيانات المقابل |
|---|---|
WEBHOOK_DATA_TYPE_ACTIVE_MINUTES |
active-minutes |
WEBHOOK_DATA_TYPE_ACTIVE_ZONE_MINUTES |
active-zone-minutes |
WEBHOOK_DATA_TYPE_ACTIVITY_LEVEL |
activity-level |
WEBHOOK_DATA_TYPE_ALTITUDE |
altitude |
WEBHOOK_DATA_TYPE_BLOOD_GLUCOSE |
blood-glucose |
WEBHOOK_DATA_TYPE_BODY_FAT |
body-fat |
WEBHOOK_DATA_TYPE_CALORIES_IN_HEART_RATE_ZONE |
calories-in-heart-rate-zone |
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_VARIABILITY |
daily-heart-rate-variability |
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_ZONES |
daily-heart-rate-zones |
WEBHOOK_DATA_TYPE_DAILY_OXYGEN_SATURATION |
daily-oxygen-saturation |
WEBHOOK_DATA_TYPE_DAILY_RESPIRATORY_RATE |
daily-respiratory-rate |
WEBHOOK_DATA_TYPE_DAILY_RESTING_HEART_RATE |
daily-resting-heart-rate |
WEBHOOK_DATA_TYPE_DAILY_SLEEP_TEMPERATURE_DERIVATIONS |
daily-sleep-temperature-derivations |
WEBHOOK_DATA_TYPE_DISTANCE |
distance |
WEBHOOK_DATA_TYPE_EXERCISE |
exercise |
WEBHOOK_DATA_TYPE_FLOORS |
floors |
WEBHOOK_DATA_TYPE_HEART_RATE |
heart-rate |
WEBHOOK_DATA_TYPE_HEART_RATE_VARIABILITY |
heart-rate-variability |
WEBHOOK_DATA_TYPE_HEIGHT |
height |
WEBHOOK_DATA_TYPE_HYDRATION_LOG |
hydration-log |
WEBHOOK_DATA_TYPE_NUTRITION_LOG |
nutrition-log |
WEBHOOK_DATA_TYPE_RESPIRATORY_RATE_SLEEP_SUMMARY |
respiratory-rate-sleep-summary |
WEBHOOK_DATA_TYPE_RUN_VO2_MAX |
run-vo2-max |
WEBHOOK_DATA_TYPE_SEDENTARY_PERIOD |
sedentary-period |
WEBHOOK_DATA_TYPE_SLEEP |
sleep |
WEBHOOK_DATA_TYPE_STEPS |
steps |
WEBHOOK_DATA_TYPE_TIME_IN_HEART_RATE_ZONE |
time-in-heart-rate-zone |
WEBHOOK_DATA_TYPE_WEIGHT |
weight |
WEBHOOK_DATA_TYPE_USER_DELETED |
user-deleted (حدث في النظام) |
WEBHOOK_DATA_TYPE_USER_REVOKED_ACCESS |
user-revoked-access (حدث في النظام) |
تجميع التعديلات
للحدّ من حركة بيانات الشبكة، تجمع Google Health API الرسائل معًا. تم ضبط النظام لإرسال 99 رسالة كحد أقصى لكل دفعة، ويتم إرسالها تلقائيًا عندما تصبح متاحة.
عند تجميع الرسائل، يتم تسليم الحمولة كمصفوفة JSON تحتوي على عناصر إشعارات متعددة. يمكن أن تتضمّن الدفعة الواحدة تعديلات لعدة مستخدمين في أنواع بيانات متعددة تم الاشتراك فيها. للاطّلاع على مثال على الحمولة، يُرجى مراجعة مثال Batch (تعدُّد المستخدمين وأنواع البيانات) في قسم "تنسيق الإشعار".
الردّ على إشعار
يجب أن يتحقّق الخادم من صحة العنوان Authorization، وأن يعالج عملية تأكيد الاتصال المتزامنة من خلال التحقّق من نقطة النهاية، وأن يستجيب لإشعارات تغيير البيانات باستخدام رمز حالة HTTP 204 No Content على الفور. لتجنُّب
انتهاء المهلة، يمكنك معالجة حمولة الإشعار بشكل غير متزامن بعد إرسال
الردّ. إذا تلقّت Google Health API أي رمز حالة آخر أو انتهت مهلة الطلب، ستعيد محاولة إرسال الإشعار لاحقًا.
مثال على Node.js (Express):
app.post('/webhook-receiver', (req, res) => {
if (req.headers.authorization !== EXPECTED_SECRET) {
return res.status(401).send();
}
if (req.body && !Array.isArray(req.body) && req.body.type === 'verification') {
return res.status(200).send();
}
// 1. Immediately acknowledge the notification batch
res.status(204).send();
// 2. Normalize single-object or batched array notifications and reconcile asynchronously
const notifications = Array.isArray(req.body) ? req.body : [req.body];
setImmediate(async () => {
for (const notification of notifications) {
const { healthUserId, dataType, intervals = [] } = notification.data || {};
console.log(`Update for user ${healthUserId} of type ${dataType}`);
// Query /v4/users/${healthUserId}/dataTypes/${dataType}/dataPoints:reconcile?filter=...
// for each interval in `intervals` (using >= and < comparators; for sleep, filter on
// sleep.interval.end_time or sleep.interval.civil_end_time).
}
});
});
لجلب البيانات المعدَّلة لكل فترة زمنية تم إرسال إشعار بشأنها، يمكنك استدعاء نقطة النهاية
reconcile
باستخدام فلتر للنطاق الزمني للفترة. ويؤدي ذلك إلى إزالة الفترات المتداخلة تلقائيًا من الأجهزة المتصلة. لمعرفة التفاصيل والأمثلة، يُرجى الاطّلاع على الحصول على عرض تسوية لبيانات الفواصل الزمنية.
هناك ثلاث استراتيجيات شائعة لتحديث قاعدة البيانات بعد تلقي إشعار تغيير البيانات:
- وضع الإشعارات في قائمة انتظار (إجراء يُنصح به): يمكنك وضع الإشعارات الواردة في قائمة انتظار الرسائل ومعالجتها خارج قائمة الانتظار استنادًا إلى موارد النظام.
- الاسترداد الفوري: يمكنك توجيه الخلفية لطلب Google Health API على الفور لاسترداد البيانات المعدَّلة وحفظها في قاعدة بياناتك.
- التحديثات الكسولة: يمكنك وضع علامة على سجلات قاعدة البيانات المحلية للمستخدم على أنّها غير صالحة، ولا يتم جلب البيانات المعدَّلة من Google Health API إلا عندما يزور المستخدم تطبيقك في المرة التالية.
تتيح لك استراتيجية إضافة الإشعارات إلى قائمة الانتظار معالجة البيانات في الوقت الفعلي تقريبًا مع الحفاظ على المرونة في مواجهة تدفق الإشعارات (على سبيل المثال، إذا تسبب انقطاع الخدمة في تراكم الإشعارات التي سيتم تسليمها دفعة واحدة). على الرغم من أنّه يمكنك اختيار معالجة قوائم الانتظار هذه وفقًا لجدول زمني طويل الفاصل الزمني (على سبيل المثال، كل 3 ساعات) لتوفير الموارد، فإنّ العيب هو أنّ المستخدمين يتوقّعون عادةً رؤية بياناتهم محدّثة في الوقت الفعلي تقريبًا.
أفضل الممارسات
اتّبِع أفضل الممارسات التالية لضمان معالجة تعديلات البيانات بشكل موثوق وفعّال:
- استخدام Subscription API: يمكنك استخدام Subscription API لتلقّي إشعارات عندما تتوفّر بيانات جديدة يمكن للمستخدم تنزيلها بدلاً من نقاط نهاية الاستطلاع.
- وضع الإشعارات في قائمة انتظار ومعالجتها بشكل منفصل: عند تلقّي إشعارات الاشتراك، ضَعها في قائمة انتظار وعالِجها بشكل منفصل بناءً على موارد نظامك. يجب أن تكون نقطة نهاية الويب هوك خفيفة من خلال الإقرار بالطلب على الفور.
التحقّق من التوقيع
لضمان صحة إشعارات Webhooks، يتم توقيع حمولة JSON الأولية لكل إشعار webhook صادر باستخدام مفتاح خاص من خلال PublicKeySign من Tink، ما يوفّر التوقيع المرمَّز بترميز Base64 في عنوان HTTP GOOGLE-HEALTH-API-SIGNATURE في الطلب. يتم تبديل مفاتيح التوقيع هذه تلقائيًا كل 30 يومًا، ويتم توزيع مجموعة المفاتيح العامة الرسمية المقابلة كملف JSON على عنوان URL الدائم https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json.
كيفية التحقّق من التوقيع
استخدام Tink (يُنصح به): يمكن للمطوّرين التحقّق من صحة التوقيع باستخدام العنصر الأساسي
PublicKeyVerify
في Tink. يمكنك جلب مجموعة المفاتيح العامة من عنوان URL الدائم، وإنشاء مثيل
PublicKeyVerify الأساسي باستخدام مجموعة المفاتيح، والتحقّق من صحة عنوان
GOOGLE-HEALTH-API-SIGNATURE الذي تم فك ترميزه مقابل حمولة JSON الأولية لخطاف الويب.
التحقّق اليدوي (بدون Tink): إذا اختار المطوّرون عدم استخدام Tink، يمكنهم التحقّق من التوقيع يدويًا باتّباع الخطوات التالية:
- يتم فك ترميز Base64 لرأس
GOOGLE-HEALTH-API-SIGNATUREلفصل بادئة Tink المكوّنة من 5 بايت (والتي تحتوي على بادئة إصدار مكوّنة من بايت واحد ومعرّف مفتاح مكوّن من 4 بايت) عن التوقيع الفعلي بترميز DER. - يمكنك جلب مجموعة مفاتيح JSON من https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json.
- ابحث عن المفتاح الذي يتطابق مع keyId الذي تم تحليله، وفك ترميز Base64 لحقل القيمة الذي يحتوي على مخزن بروتوكول EcdsaPublicKey متسلسل.
- استخرِج إحداثيات x وy بتنسيق big-endian (علامات Protobuf 3 و4) من هذه الحمولة الثنائية.
- أنشئ نسخة من مفتاح ECDSA P-256 العام العادي في مكتبة تشفير مدمجة باستخدام الإحداثيات x وy المستخرَجة.
- تحقَّق من حمولة JSON الأولية لخطاف الويب مقابل توقيع DER المستخرَج باستخدام خوارزمية SHA-256.
حالة الاشتراك واسترداده
إذا أصبحت نقطة نهاية المشترك غير متاحة أو عرضت رمز حالة خطأ (أي رمز غير 204)، تخزّن Google Health API الإشعارات المعلّقة لمدة تصل إلى 7 أيام وتعيد محاولة تسليمها باستخدام استراتيجية الانتظار الأسي.
بعد أن تصبح نقطة النهاية متصلة بالإنترنت وتستجيب بالرمز 204، ستُرسل واجهة برمجة التطبيقات
تلقائيًا الرسائل المتراكمة المخزَّنة. يتم تجاهل الإشعارات التي مرّ عليها أكثر من 7 أيام ولا يمكن استردادها.
الأخطاء الشائعة
| رمز الخطأ | رسالة | الوصف | الاقتراح |
|---|---|---|---|
| 400 طلب غير صالح | رقم المشروع غير صالح في اسم المورد | عند حذف مشترك أو تعديله باستخدام رقم تعريف مشروع Google Cloud في عنوان URL للطلب بدلاً من رقم المشروع ينطبق ذلك على اشتراكات الويب هوك التي تستخدم نقطة النهاية projects.subscribers. |
استخدِم رقم مشروع Google Cloud في عنوان URL للطلب، وليس رقم تعريف المشروع. |
| 403 محظور | لا يملك المتصل الإذن | عند إنشاء المشتركين أو إدراجهم باستخدام رقم تعريف مشروعك على Google Cloud في عنوان URL للطلب بدلاً من رقم المشروع ينطبق ذلك على اشتراكات الويب هوك التي تستخدم نقطة النهاية projects.subscribers. |
استخدِم رقم مشروع Google Cloud في عنوان URL للطلب، وليس رقم تعريف المشروع. |