المستخدمون والمزامنة
المستخدمون والمزامنة
كل ما يحتاجه تطبيق مستهلك بتسجيل دخول: إنشاء الحساب/تسجيل الدخول، إعدادات الملف الشخصي والخصوصية، إدارة الأجهزة/الجلسات، تصدير البيانات وحذف الحساب (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": "[email protected]", "name": "Lina", "password": "superStrongPass123!" }'
{
"user": { "id": "…", "email": "[email protected]", "name": "Lina", "roles": ["user"] },
"sessionId": "3f6f2c1e-…",
"accessToken": "eyJhbGciOi…"
}
accessToken هو Bearer JWT طويل العمر مرتبط بـsessionId — خزّنه بأمان وأرسله مع كل استدعاء خاص بالمستخدم. إبطال الجلسة (تسجيل الخروج، إدارة الأجهزة) يُميت الرمز من جهة الخادم.
POST /auth/login
الجسم نفسه (email، password) والمغلّف نفسه في الاستجابة كما في التسجيل. الحساب المعطَّل أو بيانات الاعتماد الخاطئة تعيد 400. وكما في التسجيل، لا يُطلب اختبار تحقق أبداً عند الاستدعاء بمفتاح API — حقل turnstileToken موجود فقط لنموذج المتصفح الخاص بموقع Navvo.
POST /auth/firebase ليس له كلمة مرور في نافّو — فبصمته
المخزَّنة عشوائية عمدًا. أما الحسابات المُنشأة بمزوّد البريد وكلمة المرور في Firebase فكلمة
مرورها حقيقية لكن Firebase هو من يحفظها، لذا تتحقّق هذه النقطة منها لدى Firebase وتصدر عند النجاح
جلسة نافّو المعتادة. ولا يتغيّر شيء بالنسبة للمستدعي: الطلب نفسه والمغلّف نفسه.أما الحسابات المُنشأة بمزوّد اجتماعي (Google وApple…) فلا كلمة مرور لها أصلًا، وتعيد 400 مع
code: "PROVIDER_ACCOUNT" مسمّيةً المزوّد والمكان الذي تُبادَل عنده رموزه:{
"statusCode": 400,
"error": "Bad Request",
"message": "This account signs in with Google. …",
"code": "PROVIDER_ACCOUNT",
"details": { "signInMethod": "provider", "provider": "google.com", "exchangeEndpoint": "/api/v1/auth/firebase" },
"requestId": "…"
}
code لا على الرسالة. ولا يُحتسب PROVIDER_ACCOUNT ضمن قفل المحاولات لأنه ليس تخمينًا
فاشلًا. أما كلمة المرور الخاطئة فعلًا فتظل تعيد Invalid credentials المعتادة، وتُحتسب.GET /auth/me
المستخدم المسجَّل دخوله + الجلسة الحالية.
curl -s "https://navvo.io/api/v1/auth/me" -H "authorization: Bearer $NAVVO_USER_TOKEN"
{
"user": { "id": "…", "email": "[email protected]", "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 /me/notifications
صندوق إشعارات المستخدم المسجَّل دخوله — كل إشعار أرسلته نافّو له، الأحدث أولًا، ويُسجَّل وقت الإرسال بصرف النظر عن وصول الدفع (push) فعليًا إلى أي جهاز. هذا ما يُبنى عليه سجل الإشعارات داخل التطبيق؛ وهو ليس إيصال تسليم لجهاز بعينه.
curl "https://navvo.io/api/v1/me/notifications?limit=50" \
-H "authorization: Bearer $TOKEN"
معاملات الاستعلام (اختيارية كلها):
| المعامل | النوع | ملاحظات |
|---|---|---|
limit | عدد صحيح | ١–٢٠٠، والافتراضي ٥٠ |
offset | عدد صحيح | ≥ ٠، والافتراضي ٠ |
type | نص | لإرجاع إشعارات نوع واحد فقط — راجع الجدول أدناه |
أنواع الإشعارات
type نص حر، لا تعداد ثابت يجب ترميزه مسبقًا — قد تظهر أنواع إشعارات جديدة مع الوقت دون أن يكون
ذلك تغييرًا كاسرًا. هذه هي القائمة الكاملة لما ترسله نافّو فعليًا اليوم؛ لا شيء هنا مخطَّط له أو
افتراضي:
type | يُرسَل عند | حمولة data |
|---|---|---|
commute_leave_now | إطلاق تنبيه وقت مغادرة لرحلة يومية محفوظة — راجع الرحلات اليومية | { "commuteId", "minutesBefore" } |
admin_broadcast | إرسال المشغّل إعلانًا على مستوى المنصة | غير مضبوطة |
الاستجابة — صندوق فيه عناصر
{
"items": [
{
"id": "9c3f2e10-…",
"type": "commute_leave_now",
"title": "Navvo · حان وقت الانطلاق",
"body": "غادر خلال ~١٥ دقيقة لـ\"العمل\" — ~٢٢ دقيقة قيادة للوصول بحلول ٠٨:٣٠.",
"url": "/map?from=31.95,35.91&to=31.96,35.93&navigate=1",
"data": { "commuteId": "4a1d…", "minutesBefore": 15 },
"isRead": false,
"readAt": null,
"createdAt": "2026-08-27T05:14:02.000Z"
},
{
"id": "7b1a44c2-…",
"type": "admin_broadcast",
"title": "نافّو تضيف السعودية",
"body": "التوجيه والبحث يتوسّعان إلى السعودية خلال الأسابيع القادمة.",
"url": null,
"data": null,
"isRead": true,
"readAt": "2026-08-26T09:00:11.000Z",
"createdAt": "2026-08-25T18:30:00.000Z"
}
],
"total": 2,
"limit": 50,
"offset": 0
}
الاستجابة — صندوق فارغ
مستخدم لم يتلقَّ أي إشعار قط يحصل على مصفوفة فارغة، لا خطأ ولا قيمة فارغة (null):
{ "items": [], "total": 0, "limit": 50, "offset": 0 }
الاستجابة — التصفية بالنوع
GET /me/notifications?type=admin_broadcast تعيد الغلاف نفسه، مقتصرًا على ذلك النوع؛ ويعكس
total العدد بعد التصفية لا صندوق الإشعارات كاملًا.
استجابات الخطأ
نفس غلاف الأخطاء في بقية الواجهة. حالتان سترياهما فعليًا في هذه النقطة:
رمز دخول (bearer token) مفقود أو غير صالح — 401:
{
"message": "Missing bearer token",
"error": "Unauthorized",
"statusCode": 401,
"code": "UNAUTHENTICATED",
"requestId": "2fa48173-…"
}
limit/offset خارج المدى المسموح — 400:
{
"statusCode": 400,
"error": "Bad Request",
"message": ["limit must not be greater than 200"],
"code": "VALIDATION_ERROR",
"requestId": "e9289fd5-…"
}
الأماكن المحفوظة
مفضّلات المستخدم باسم مخصص وأيقونة وملاحظة وقائمة ووسوم — تتزامن عبر الأجهزة.
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/PATCH أيضًا كي تستخدم النتيجة دون إعادة جلب — بهذا الشكل:
{
"id": "6f1c…", "type": "favorite", "label": "Ardh cafe",
"lat": 31.990558, "lng": 35.880810,
"location": { "x": 35.880810, "y": 31.990558 },
"metadata": {
"name": "Ardh cafe", "detail": "Rainbow St", "placeId": "31c5a4e2-…",
"customName": null, "note": null, "icon": null, "listName": null, "tags": []
},
"createdAt": "…", "updatedAt": "…"
}
lat وlng. أما location فهي الهندسة المخزَّنة الخام وشكلها يتبع مشغّل قاعدة البيانات — وهي حاليًا كائن { x, y } حيث x خط الطول وy خط العرض، أي عكس ترتيب lat,lng المعتمد في بقية الواجهة. أما lat وlng فأرقام صريحة تعني ما تقوله دائمًا. تعامل مع location كقيمة مبهمة.وتوجد حقول المستخدم داخل metadata لا في المستوى الأعلى: customName وnote وicon وlistName وtags جميعها متداخلة هناك. أما label فهو اسم العرض الذي يحافظ عليه الخادم (يتبع customName عند ضبطه، وإلا فيعود إلى name).
GET · POST /me/locations
مراسٍ مثبَّتة مثل المنزل والعمل: { "type": "home" | "work" | "favorite" | "custom", "label", "lat", "lng" }.
يعرضها GET وكلٌّ منها يحمل lat و**lng** كأرقام صريحة إلى جانب هندسة location الخام. اقرأ الأرقام لا الهندسة — انظر التحذير أعلاه.
DELETE /me/locations/{id}— حذف مرساة مثبَّتة واحدة. وهي محصورة بالمستخدم المُستدعي؛ فمعرّف مستخدم آخر يعيد404لا بيانات ذلك المستخدم.
القوائم — GET · POST /me/lists
مجموعات مسمّاة من أماكن الدليل. لكل حساب أربع قوائم افتراضية تُنشأ تلقائيًا عند أول تعامل مع هذه الواجهة:
kind | الاسم | الأيقونة |
|---|---|---|
favourites | Favourites | heart |
want-to-go | Want to go | bookmark |
saved-trips | Saved Trips | route |
labelled | Labelled | tag |
القائمة الافتراضية قائمة عادية في كل شيء عدا أنها لا تُحذف: يمكن إعادة تسميتها وتغيير أيقونتها ومشاركتها وإخفاؤها عن الخريطة وتفريغها. طابِقها على kind لا على name، فللمستخدم أن يعيد تسمية Favourites كما يشاء.
GET /me/lists
{
"lists": [
{
"id": "9f3c…", "kind": "favourites", "name": "Favourites", "icon": "heart",
"iconLightUrl": "https://navvo.io/uploads/list-icons/heart-light.svg",
"iconDarkUrl": "https://navvo.io/uploads/list-icons/heart-dark.svg",
"system": true, "public": false, "hiddenOnMap": false,
"shareSlug": "favourites-8a1c4d02", "shareUrl": null,
"count": 1,
"canDelete": false,
"deleteBlockedReason": "A default list cannot be deleted",
"createdAt": "…", "updatedAt": "…",
"places": [
{
"savedPlaceId": "b71e…", "placeId": "31c5a4e2-…", "slug": "ardh-cafe-ard-kafyh-2bd24a",
"nameEn": "Ardh cafe", "nameAr": "…", "categories": ["cafe"], "rating": 4.6,
"lat": 31.953, "lng": 35.913,
"imageUrl": "https://navvo.io/uploads/places/…/a7f3.webp",
"imageSource": "photo", "imageWidth": 408, "imageHeight": 544,
"note": "try the flat white", "addedAt": "…"
}
]
}
],
"total": 4,
"totalPlaces": 1
}
| الحقل | النوع | الوصف |
|---|---|---|
kind | string | null | إحدى القوائم الافتراضية الأربع، أو null لقائمة أنشأها المستخدم. |
icon | string | null | اسم الأيقونة. طابِق عليه إن كنت تشحن مجموعة أيقوناتك الخاصة. |
iconLightUrl / iconDarkUrl | string | null | روابط مطلقة لملف SVG بمقاس 24 × 24 للأيقونة — ضعها مباشرة في <img>. وتكون كلتاهما null إن لم يكن اسم الأيقونة ضمن ما تشحنه Navvo (انظر أدناه). |
system | boolean | true للقائمة الافتراضية. |
hiddenOnMap | boolean | أخفى المستخدم أماكن هذه القائمة عن خريطته. عرضيّ فقط — الأماكن تُعاد كما هي. |
shareUrl | string | null | ليس فارغًا إلا بينما public تساوي true. |
count | number | عدد الأماكن في القائمة. |
canDelete | boolean | هل سينجح DELETE الآن. |
deleteBlockedReason | string | null | سبب المنع حين تكون canDelete بقيمة false. |
places[].savedPlaceId | string | معرّف العضوية — وهو ما تأخذه عمليات الحذف والنقل، لا مُعرِّف المكان أو اسمه اللطيف. |
تعود القوائم بترتيب ثابت: الأربع الافتراضية أولًا، ثم قوائم المستخدم بحسب الأحدث.
أيقونات القوائم
icon اسم، أما iconLightUrl وiconDarkUrl فملفا SVG جاهزان للعرض له، فلا يحتاج التطبيق الأصلي إلى شحن مكتبة أيقونات ليطابق الويب. اختر النسخة حسب سِمة واجهتك — فالملف الفاتح بخط داكن للخلفيات الفاتحة والعكس بالعكس.
https://navvo.io/uploads/list-icons/{icon}-{light|dark}.svg
يقبل icon أي نص في POST/PATCH، لكن لا تُعاد الروابط إلا للأيقونات التي تشحنها Navvo — وما عداها يُعاد null للحقلين بدل رابط يعطي 404. والقائمة المتاحة:
heart bookmark route tag star house briefcase map-pin flag coffee utensilsshopping-bag store plane car bed mountain trees waves camera music film bookpalette dumbbell gift baby paw-print graduation-cap building-2
والأربع الأولى هي أيقونات القوائم الافتراضية. تعامل مع القائمة على أنها مفتوحة — فقد تُضاف أسماء جديدة — وارجع إلى رمزك الخاص حين تعود الروابط بقيمة null.
canDelete وdeleteBlockedReason. فهما يخبرانك بتعطيل زر الحذف وسببه، فلا يكتشف المستخدم القاعدة عبر استجابة 409.بقية النقاط
POST /me/lists{ "name": "Weekend cafés", "public"?: false, "icon"?: "coffee" }— إنشاء قائمة. تُعيد الشكل نفسه الوارد فيGET.PATCH /me/lists/{id}{ "name"?, "public"?, "hiddenOnMap"?, "icon"? }— تعديل أي قائمة، افتراضية كانت أم لا.DELETE /me/lists/{id}— حذف قائمة. يُعاد409إن كانت افتراضية أو ما زالت تحوي أماكن — فرّغها أولًا.→ { "deleted": true, "id" }POST /me/lists/{id}/places{ "placeId": "…", "note"? }— إضافة مكان من الدليل. وإعادة إضافة مكان موجود تُحدّث ملاحظته بدل تكراره.DELETE /me/lists/{id}/places/{savedPlaceId}— إزالة مكان واحد من قائمة.PATCH /me/lists/{id}/places/{savedPlaceId}{ "toListId": "…" }— نقل مكان إلى قائمة أخرى. نقل حقيقي، فتنتقل الملاحظة معه ولا يمرّ المكان بلحظة لا ينتمي فيها إلى أي قائمة. وإن كانت الوجهة تحويه أصلًا فيُدمجان (mergedWithExisting: true) بدل التكرار.→ { "moved": true, "savedPlaceId", "fromListId", "toListId", "mergedWithExisting" }POST /me/lists/{id}/feedback{ "message": "…", "category"? }— إرسال ملاحظات حول قائمة.→ { "ok": true, "id" }
GET /shared-lists/{shareSlug} — عام
عارض القوائم المشتركة — دون مصادقة؛ المعرّف هو السر، ولا تُحلّ إلا القوائم التي وسمها المالك بأنها public. الاستجابة منقّاة (لا معرّفات مستخدمين):
curl -s "https://navvo.io/api/v1/shared-lists/weekend-cafes-a1b2c3"
{
"found": true, "name": "مقاهي نهاية الأسبوع", "updatedAt": "…",
"places": [
{ "slug": "ardh-cafe-ard-kafyh-2bd24a", "nameEn": "Ardh cafe", "nameAr": "…",
"categories": ["cafe"], "rating": 4.6, "center": "POINT(35.913 31.953)", "note": null }
]
}
المعرّف المجهول/الخاص يعيد { "found": false }.
GET /me/shared-lists/{slug} القائمة نفسها لمالكها، برمز Bearer بدل الاعتماد على سرّية المُعرِّف. وهي تُجيب بـ 401 دون رمز، لذا استخدم الصيغة العامة /shared-lists/{slug} لروابط المشاركة، وهذه داخل واجهة حساب موثَّقة.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 الذكية المباشرة لفهم الاستعلامات وتسميات المسارات.