المستخدمون والمزامنة
المستخدمون والمزامنة
كل ما يحتاجه تطبيق مستهلك بتسجيل دخول: إنشاء الحساب/تسجيل الدخول، إعدادات الملف الشخصي والخصوصية، إدارة الأجهزة/الجلسات، تصدير البيانات وحذف الحساب (GDPR)، الأماكن المحفوظة والقوائم القابلة للمشاركة، سجل البحث/الزيارات، ومشاركة الموقع الحي مع وقت الوصول المتوقع. هذه هي الواجهة نفسها التي يعمل عليها تطبيق خرائط Navvo.
Authorization: Bearer <accessToken> من POST /auth/login) — وليس بمفتاح x-api-key. النقاط الموسومة بأنها عامة لا تحتاج أي اعتماد (مفتاح/معرّف المشاركة هو السر).الحسابات والملف الشخصي
POST /auth/register
إنشاء حساب مستخدم. مجهول الهوية بطبيعته.
| الحقل | النوع | ملاحظات |
|---|---|---|
email | string | مطلوب — بريد إلكتروني صالح، يُخزَّن بأحرف صغيرة |
password | string | مطلوب — 10 أحرف على الأقل |
name | string | اسم عرض اختياري |
turnstileToken | string | خاص بالمتصفح فقط: يخصّ نموذج تسجيل الدخول في موقع Navvo نفسه. عملاء الـ API الذين يستدعون بـ x-api-key لا يخضعون أبداً لاختبار التحقق ويمكنهم إغفال هذا الحقل كلياً |
curl -s -X POST "https://navvo.io/api/v1/auth/register" \
-H "content-type: application/json" \
-d '{ "email": "lina@example.com", "name": "Lina", "password": "superStrongPass123!" }'
{
"user": { "id": "…", "email": "lina@example.com", "name": "Lina", "roles": ["user"] },
"sessionId": "3f6f2c1e-…",
"accessToken": "eyJhbGciOi…"
}
accessToken هو Bearer JWT طويل العمر مرتبط بـsessionId — خزّنه بأمان وأرسله مع كل استدعاء خاص بالمستخدم. إبطال الجلسة (تسجيل الخروج، إدارة الأجهزة) يُميت الرمز من جهة الخادم.
POST /auth/login
الجسم نفسه (email، password) والمغلّف نفسه في الاستجابة كما في التسجيل. الحساب المعطَّل أو بيانات الاعتماد الخاطئة تعيد 400. وكما في التسجيل، لا يُطلب اختبار تحقق أبداً عند الاستدعاء بمفتاح API — حقل turnstileToken موجود فقط لنموذج المتصفح الخاص بموقع Navvo.
GET /auth/me
المستخدم المسجَّل دخوله + الجلسة الحالية.
curl -s "https://navvo.io/api/v1/auth/me" -H "authorization: Bearer $NAVVO_USER_TOKEN"
{
"user": { "id": "…", "email": "lina@example.com", "name": "Lina", "roles": ["user"],
"profile": { "avatar": { "type": "emoji", "value": "🌟" }, "privacy": { "saveHistory": true } } },
"session": { "id": "…", "sessionId": "…", "lastSeenAt": "…", "expiresAt": "…", "revokedAt": null }
}
PATCH /auth/me
تحديث الملف الشخصي القابل للتعديل. كل الحقول اختيارية؛ لا يتغيّر إلا ما تُرسله.
| الحقل | النوع | ملاحظات |
|---|---|---|
name | string | اسم العرض (يُشذَّب، بحد أقصى 160 حرفاً) |
avatar | object | null | { type: "image" | "emoji" | "letter", value, bgColor? }؛ وnull يمسح الصورة الرمزية |
privacy | object | null | مفاتيح الخصوصية — مفاتيح منطقية ضمن قائمة مسموحة: saveHistory، personalization، shareAnalytics، useLocation؛ وnull يمسح الحزمة |
curl -s -X PATCH "https://navvo.io/api/v1/auth/me" \
-H "authorization: Bearer $NAVVO_USER_TOKEN" -H "content-type: application/json" \
-d '{ "privacy": { "saveHistory": false, "personalization": true } }'
→ { "ok": true, "user": { … } }. يقرأ العميل الإعدادات مجدداً من GET /auth/me → user.profile.privacy. احترم saveHistory: false بعدم استدعاء POST /me/history.
POST /auth/logout
تسجيل خروج الجلسة الحالية من جهة الخادم (يُبطَل معرّف جلسة الرمز، فيتوقف الرمز عن العمل في كل مكان). → { "ok": true }
GET /auth/sessions · DELETE /auth/sessions
إدارة الأجهزة — اعرض جلسات المستخدم وأبطِلها.
{
"items": [
{ "sessionId": "…", "current": true, "ipAddress": "94.…", "userAgent": "Mozilla/5.0 …",
"lastSeenAt": "…", "createdAt": "…", "expiresAt": "…", "revokedAt": null }
]
}
DELETE /auth/sessions/{sessionId}— إبطال جلسة واحدة →{ "ok": true, "revoked": 1 }DELETE /auth/sessions?all=1— «تسجيل الخروج من كل مكان آخر»: يُبطل كل الجلسات عدا الحالية →{ "ok": true, "revoked": n }
GET /auth/me/export
تصدير البيانات بأسلوب GDPR — كل ما تخزّنه Navvo تحت الحساب، في مستند JSON واحد: { exportedAt, account, savedLocations, mapHistory, liveShares, signDisregards, sessions }.
DELETE /auth/me
حذف الحساب ذاتياً (متطلَّب متاجر التطبيقات). يمسح بيانات المستخدم تباعاً — الجلسات، الأماكن المحفوظة والسجل، مشاركات الموقع الحي — ثم يزيل الحساب.
| الحقل | النوع | ملاحظات |
|---|---|---|
confirm | string | مطلوب — يجب أن يكون النص الحرفي DELETE |
password | string | مطلوب عندما يملك الحساب كلمة مرور |
→ { "deleted": true }
تسجيل الدخول الاجتماعي (OAuth)
المزوّدون يُهيّئهم مشغّل المنصة — اعرض الأزرار دائماً من القائمة الحية:
GET /auth/providers(عام) →{ "providers": [ { "id": "google", "label": "Google", … } ], "turnstile": { "enabled": true, "siteKey": "…" } }GET /auth/oauth/{provider}/start?next=/map— يعيد توجيه المتصفح (302) إلى صفحة موافقة المزوّد.GET /auth/oauth/{provider}/callback— يعود المزوّد إلى هنا؛ عند النجاح يهبط المتصفح على/map#nvauth=ok&token=<accessToken>. إذا كان البريد يعود لحساب بكلمة مرور، يكون الجزءnvauth=linkويؤكد العميل الربط عبرPOST /auth/oauth/linkبجسم{ linkToken, password? }.
POST /auth/firebase
تبادل تسجيل الدخول عبر Firebase — المسار الموصى به للتطبيقات التي تستخدم Firebase Authentication (بريد/كلمة مرور، Google، Apple، Microsoft، Facebook، GitHub…). سجِّل دخول المستخدم عبر Firebase SDK ثم أرسل رمز المعرّف (ID token)؛ تتحقق Navvo منه مقابل شهادات Google العامة (المُصدِر والجمهور مثبّتان على مشروع Navvo)، وتجد الحساب أو تنشئه عبر البريد الموثَّق، وتعيد مغلّف المصادقة القياسي (user، sessionId، accessToken) — فيحصل المستخدم فوراً على وصول كامل لخدمات الأعضاء (الملاحة، أطلس، الأماكن المحفوظة…).
| الحقل | النوع | ملاحظات |
|---|---|---|
idToken | string | مطلوب — رمز معرّف Firebase من getIdToken() |
نموذج الوصول: الزائر مقابل المسجَّل
الخريطة الأساسية (البلاطات، الأنماط، التصفح، البحث، تفاصيل الأماكن، قراءات الترميز الجغرافي) مفتوحة. خدمات الأعضاء تتطلب رمز Bearer لمستخدم مسجَّل — أو مفتاح API الخاص بك كمطوّر: التوجيه/الملاحة (POST /routing/*، POST /traffic/route)، وكيل أطلس، الأماكن المحفوظة والقوائم، السجل، المشاركة الحية، التبليغ، ورموز الإشعارات. الاستدعاءات المجهولة لهذه تعيد 401.
رموز الإشعارات (Push)
سجِّل رمز FCM الخاص بالجهاز ليتمكن خادمك (أو Navvo عندما يفعّل المشغّل الإرسال) من الوصول للمستخدم:
POST /me/push-tokens— الجسم{ "token": "…", "platform": "web" | "android" | "ios" }(مصادقة Bearer). إعادة إرسال رمز موجود تعيد ربطه بالمستخدم الحالي.DELETE /me/push-tokens/{token}— لإلغاء التسجيل عند الخروج.
الأماكن المحفوظة
مفضّلات المستخدم باسم مخصص وأيقونة وملاحظة وقائمة ووسوم — تتزامن عبر الأجهزة.
GET · POST /me/saved-places
GET يعيد أحدث 100 من المفضلة. POST يحفظ نقطة:
| الحقل | النوع | ملاحظات |
|---|---|---|
name | string | مطلوب — اسم المكان/النقطة |
lat / lng | number | مطلوب |
detail | string | عنوان فرعي/عنوان اختياري |
placeId | string | معرّف مكان Navvo اختياري — يضيف المكان أيضاً إلى قائمة «Saved places» للمستخدم |
customName | string | اسم عرض يختاره المستخدم (اختياري) |
note | string | ملاحظة خاصة (اختياري) |
icon | string | أيقونة/إيموجي (اختياري) |
listName | string | تسمية تجميع (اختياري) |
tags | string | وسوم مفصولة بفواصل (بحد أقصى 12) |
PATCH /me/saved-places/{id}— تحديثcustomName،note،icon،listName،tags.DELETE /me/saved-places/{id}→{ "deleted": true, "id" }.
GET · POST /me/locations
مراسٍ مثبَّتة مثل المنزل والعمل: { "type": "home" | "work" | "favorite" | "custom", "label", "lat", "lng" }. يعرضها GET (الهندسة المخزّنة WKT بالصيغة POINT(<lng> <lat>) — خط الطول أولاً).
القوائم — GET · POST /me/lists
مجموعات مُسمّاة من أماكن الفهرس، قابلة للمشاركة اختيارياً.
POST /me/listsبجسم{ "name": "مقاهي نهاية الأسبوع", "public": false }— كل قائمة تحصل علىshareSlugفريد؛ اضبط"public": trueكي يعمل رابط مشاركتها.GET /me/lists— قوائم المستخدم مع أماكنها.POST /me/lists/{id}/placesبجسم{ "placeId": "…", "note"? }— إضافة مكان من الفهرس إلى قائمة.
GET /shared-lists/{shareSlug} — عام
عارض القوائم المشتركة — دون مصادقة؛ المعرّف هو السر، ولا تُحلّ إلا القوائم التي وسمها المالك بأنها public. الاستجابة منقّاة (لا معرّفات مستخدمين):
curl -s "https://navvo.io/api/v1/shared-lists/weekend-cafes-a1b2c3"
{
"found": true, "name": "مقاهي نهاية الأسبوع", "updatedAt": "…",
"places": [
{ "slug": "jordan-beans-cafe", "nameEn": "Jordan Beans Cafe", "nameAr": "…",
"categories": ["cafe"], "rating": 4.6, "center": "POINT(35.913 31.953)", "note": null }
]
}
المعرّف المجهول/الخاص يعيد { "found": false }.
GET · POST · DELETE /me/history
سجل بحث/زيارات المستخدم (الأحدث أولاً، ويُعاد 100 كحد أقصى).
GET /me/history→{ "items": [ … ], "total" }POST /me/historyبجسم{ "name", "lat", "lng", "detail"?, "placeId"? }— تسجيل مُدخَلDELETE /me/history— مسح الكل →{ "deleted": true }DELETE /me/history/{id}— إزالة مُدخَل واحد
الرحلات اليومية (وقت المغادرة + التنبيهات)
رحلات محفوظة (منزل→عمل ونحوها)، لكل منها أيام تكرار، وعمر دائم أو مؤقّت، وأي عدد من أوقات التنبيه قبل المغادرة. يقيّم الخادم كل رحلة مُفعّلة كل دقيقة وفق حركة المرور الحية، وعند اقتراب وقت المغادرة يرسل إشعاراً (عبر رموز الإشعارات المسجّلة للمستخدم) — مثل «غادر خلال ~15 دقيقة إلى العمل».
كل المسارات تتطلب مصادقة Bearer ومقيّدة بالمستخدم المسجّل.
GET /me/commutes→{ "commutes": Commute[] }POST /me/commutesبجسمCommute(بدونid) →{ "commute" }(حد أقصى 20 لكل مستخدم)PUT /me/commutes/{id}(جسمCommuteجزئي) →{ "commute" }DELETE /me/commutes/{id}→{ "ok": true }
{
"id": "…",
"name": "العمل",
"from": { "lat": 31.95, "lng": 35.91, "label": "المنزل" },
"to": { "lat": 31.99, "lng": 35.95, "label": "المكتب" },
"arriveBy": "09:00",
"days": [0,1,2,3,4],
"permanent": true,
"expiresAt": null,
"notifications": [{ "minutesBefore": 30 }, { "minutesBefore": 15 }],
"enabled": true
}
مشاركة الموقع الحي
شارك موقعاً حياً تحت مفتاح متجدد يستحيل تخمينه. المشاركة تنتهي تلقائياً بعد ساعتين من آخر إشارة (ping)؛ وكل إشارة تمدّدها.
POST /me/live-share
بدء مشاركة: { "label"? } → { "shareKey": "…", "active": true, "expiresAt": "…" }. رابط العارض الذي تشاركه هو https://navvo.io/map?live=<shareKey>.
GET /me/live-share
مشاركات المستخدم النشطة: { "items": [ { "shareKey", "label", "lastPingAt", "expiresAt" } ] }.
POST /me/live-share/{key}/ping
ادفع الموقع الحالي (استدعِه كل بضع ثوانٍ أثناء المشاركة):
| الحقل | النوع | ملاحظات |
|---|---|---|
lat / lng | number | مطلوب |
heading | number | الاتجاه بالدرجات (اختياري) |
accuracy | number | دقة GPS بالأمتار (اختياري) |
destName | string | مشاركة وقت الوصول (Share-ETA) — اسم الوجهة أثناء الملاحة |
destLat / destLng | number | Share-ETA — إحداثيات الوجهة |
etaSeconds | number | Share-ETA — الثواني حتى الوصول؛ أعد إرسالها مع كل إشارة أثناء الملاحة |
→ { "active": true } (و{ "active": false } بعد الإيقاف/الانتهاء — توقف عندها عن الإرسال).
POST /me/live-share/{key}/stop
إنهاء المشاركة → { "stopped": true }.
GET /live/{key} — عام
قراءة العارض — دون مصادقة، استعلم عنها بضع مرات في الدقيقة:
{
"active": true, "lat": 31.9539, "lng": 35.9106, "heading": 270, "accuracy": 8,
"label": "Lina", "updatedAt": "…",
"destination": { "name": "المطار", "lat": 31.7226, "lng": 35.9932 },
"etaSeconds": 1240, "arrivalTime": "2026-07-09T11:42:00.000Z"
}
تظهر destination وetaSeconds وarrivalTime فقط أثناء ملاحة المُشارِك (أي عندما يرسل حقول Share-ETA مع الإشارة) — وإلا فهي null. المفاتيح المنتهية/المجهولة تعيد { "active": false }؛ والمشاركة التي بدأت ولم تُرسل إشارة بعد تعيد { "active": true, "pending": true }.
روابط عميقة إلى خريطة Navvo
سلّم المستخدم من تطبيقك إلى تجربة خريطة Navvo الكاملة بروابط بسيطة:
| الرابط | يفتح |
|---|---|
https://navvo.io/map/place/{slug} | صفحة تفاصيل مكان من الفهرس |
https://navvo.io/map?pin=31.95,35.91&name=Meet%20here | دبوساً موضوعاً عند lat,lng مع تسمية اختيارية |
https://navvo.io/map?from=31.95,35.91&to=31.72,35.99&navigate=1&mode=auto | مساراً — ومع navigate=1 تبدأ الملاحة خطوة بخطوة فوراً؛ وmode هو ملف توجيه (auto، pedestrian، bicycle، …) |
https://navvo.io/map?live=KEY | عارض المشاركة الحية الذي يتتبع مفتاح مشاركة |
GET /live/{key} لرصد الوصول، أو منطقك الخاص فوق الأماكن المحفوظة والسجل).وكيل أطلس (تحكّم لغوي)
حوِّل الأوامر بالّلغة الطبيعية إلى إجراءات خريطة مُهيكلة — بحث، اتجاهات، دبابيس، تحكّم بالطبقات، والآن خطط رحلات يومية وتحسين مسارات الأساطيل.
الصوت وتحويل الكلام إلى نص
حوّل الصوت المنطوق إلى نص (بالإنجليزية والعربية) واستدعِ مساعدات Navvo الذكية المباشرة لفهم الاستعلامات وتسميات المسارات.