Navvo
البدء

المصادقة

كيفية الحصول على مفاتيح Navvo البرمجية واستخدامها، وما النطاقات التي تتحكّم بالوصول.

المصادقة

تتم مصادقة كل طلب إلى واجهة تكامل Navvo البرمجية باستخدام مفتاح API. المفاتيح ذات نطاقات، ومحدودة المعدّل، ومرتبطة بمشروع داخل مؤسستك.

إرسال مفتاحك

مرّر المفتاح في كل طلب باستخدام ترويسة x-api-key:

curl "https://navvo.io/api/v1/search?q=pharmacy" \
  -H "x-api-key: nvvo_YOUR_KEY"

بالنسبة لعناوين URL التي يجلبها المتصفّح مباشرةً ولا يستطيع إضافة ترويسات إليها — وأهمّها بلاطات الخرائط والأنماط في Navvo Maps — مرّر المفتاح كمعامل استعلام بدلًا من ذلك. يُقبَل كلٌّ من api_key وapiKey:

https://navvo.io/api/v1/tiles/style?style=standard&api_key=nvvo_YOUR_KEY
عامِل صيغة معامل الاستعلام على أنها وسيلة ملائمة لعملاء الخرائط فقط. وفي أي مكان تتحكّم فيه بترويسات الطلب، فضّل x-api-key حتى لا ينتهي مفتاحك في السجلّات أو سجلّ المتصفّح.

صيغة المفتاح

مفاتيح Navvo مسبوقة ببادئة وسهلة التمييز:

nvvo_<48 hex characters>

تُخزَّن تجزئة المفتاح فقط على الخادم، إلى جانب الأحرف الأربعة الأخيرة (للعرض). يُعاد النص الصريح مرّة واحدة فقط، عند إنشاء المفتاح.

النطاقات

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

النطاقيمنح الوصول إلىمفعّل افتراضيًا؟
searchالبحث✅
geocodeالترميز الجغرافي (شاملاً الجملة)✅
placesالأماكن — التفاصيل، الساعات، الصور، المراجعات، التصنيفات، المهام✅
routingالتوجيه، المصفوفة، الأيزوكرون، التنقّل والمسارات✅
trafficحركة المرور والحوادث✅
telemetryالقياسات✅
tilesبلاطات الخرائط وبيانات الخريطة✅
imageryالصور✅
geoالأسيجة الجغرافية والعنونة / Plus Codes❌ (اشتراك اختياري)
insightsتجميعات رؤى Navvo الآمنة للخصوصية❌ (اشتراك اختياري)
optimizeتحسين المسارات (OR-Tools)❌ (اشتراك اختياري)

تُنشأ المفاتيح الجديدة مع تفعيل ثمانية من الأحد عشر نطاقاً. والنطاقات geo وinsights وoptimize معطّلة افتراضيًا — اطلبها صراحةً إذا كنت بحاجة إلى الأسيجة الجغرافية أو التحليلات أو التحسين.

القائمة الحيّة المرجعية متاحة أيضاً للمطوّرين المُسجَّلين عبر GET /developer/scopes (كل نطاق بتسمية ووصف).

تتطلّب نقطة النهاية المراعية لحركة المرور POST /traffic/route نطاقَي routing وtrafficكليهما.

الحصول على مفتاح

أسرع طريقة للحصول على مفتاح هي بوابة المطوّرين على navvo.io/developer — وحدة تحكّم بالنقر لإدارة المؤسسات والمشاريع والمفاتيح ومراقبة الاستخدام الحيّ وتجربة الطلبات في بيئة اختبار. كل ما يلي متاح أيضًا كواجهة REST إذا فضّلت أتمتته.

تُنشأ مفاتيح API عبر نقاط نهاية بوابة المطوّرين، وهي محميّة برمز جلسة المستخدم (رمز JWT، وليس مفتاح API). التدفّق هو: حساب ← مؤسسة ← مشروع ← مفتاح. كل مؤسسة ومشروع ومفتاح مرتبط بالمستخدم الذي أنشأه — فأنت لا ترى وتدير إلا ما يخصّك.

1. أنشئ حسابًا / سجّل الدخول

curl -X POST "https://navvo.io/api/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "name": "Your Name",
    "password": "a-strong-password-min-10-chars"
  }'

يعيد كلاهما accessToken (رمز JWT من نوع Bearer) إضافةً إلى المستخدم والجلسة الخاصّين بك:

{
  "user": { "id": "uuid", "email": "[email protected]", "name": "Your Name", "roles": ["user"] },
  "sessionId": "uuid",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

أرسل هذا الرمز بصيغة Authorization: Bearer <accessToken> في جميع طلبات /developer/* و/auth/me.

يتطلّب إصدار المفاتيح دور developer (أو admin/super_admin). التسجيل ذاتيّ الخدمة — استدعِ POST /developer/enroll (أو GET /developer/access، الذي يسجّلك تلقائيًا عند أول قراءة) مع رمز Bearer الخاصّ بك لمنح حسابك الدور بنفسك. العملية عديمة الأثر عند التكرار وتسري اعتبارًا من الطلب التالي مباشرةً، لذا يمكنك الانتقال مباشرةً من التسجيل ← الانضمام ← إنشاء مفتاح دون أي خطوة إدارية.

2. أنشئ مؤسسة

curl -X POST "https://navvo.io/api/v1/developer/organizations" \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Acme Logistics", "slug": "acme-logistics" }'

3. أنشئ مشروعًا

curl -X POST "https://navvo.io/api/v1/developer/organizations/<orgId>/projects" \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Driver App" }'

4. أنشئ مفتاح API

curl -X POST "https://navvo.io/api/v1/developer/api-keys" \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "<projectId>",
    "label": "Driver App – production",
    "plan": "starter",
    "scopes": { "geo": true }
  }'

تحتوي الاستجابة على مفتاحك في الحقل key — هذه هي المرة الوحيدة التي يُعرَض فيها:

{
  "key": "nvvo_3f9c2a1e8b7d6c5f4a3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b",
  "id": "uuid",
  "label": "Driver App – production",
  "lastFour": "9c8b",
  "scopes": {
    "search": true, "geocode": true, "places": true, "routing": true,
    "traffic": true, "telemetry": true, "tiles": true, "imagery": true, "geo": true
  },
  "plan": "starter",
  "quotaPerMinute": 255,
  "quotaPerDay": 100000,
  "unlimited": false,
  "active": true
}

يحمل كل كائن مفتاح حقلًا منطقيًا للقراءة فقط هو unlimited. تكون قيمته true فقط للمفتاح الذي جعلته Navvo غير محدود. وما دامت قيمته true يحتفظ المفتاح بقيمتَي quotaPerMinute وquotaPerDay، لكنهما لا تُفرَضان. ولا يمكنك ضبط unlimited عبر واجهة المطوّرين البرمجية: فهو، مثل أي حقل غير معروف في الجسم، يُحذَف من الطلب. تواصل مع Navvo إن احتجت إلى مفتاح غير محدود.

جسم الطلب — POST /developer/api-keys

projectId
string required
المشروع الذي ينتمي إليه هذا المفتاح.
label
string required
اسم قابل للقراءة البشرية للمفتاح (يظهر في القوائم).
plan
string
واحدة من free، starter، growth، scale، enterprise. القيمة الافتراضية free. (القيمة القديمة startup أصبحت الآن تُقابِل starter.) عند حذف الحصص الصريحة، يتبنّى المفتاح قيمتَي quotaPerMinute / quotaPerDay الافتراضيتين للخطة.
scopes
object
خريطة { scope: boolean } تُدمَج فوق القيم الافتراضية. مرّر { "geo": true } لتفعيل النطاق الاختياري، أو { "telemetry": false } لتعطيل أحدها.
quotaPerMinute
number
الحدّ الأقصى لطلبات المفتاح في الدقيقة، من 1 إلى 255 (سقف الخدمة الذاتية). القيمة الافتراضية حدّ الخطّة (free: 60).
quotaPerDay
number
الحدّ الأقصى لطلبات المفتاح في اليوم، من 1 إلى 10000000 (سقف الخدمة الذاتية). القيمة الافتراضية حدّ الخطّة (free: 5000).
restrictions
object
اختياري { "referrers": [...], "ips": [...] }: المواقع الإلكترونية وعناوين IP التي يُسمح باستخدام المفتاح منها. راجع تقييد المفتاح.

إدارة المفاتيح

تتطلّب كل هذه النقاط رمز الجلسة Authorization: Bearer <accessToken> وهي مرتبطة بحسابك.

الطريقةالمسارالغرض
POST/developer/enrollذاتيّ الخدمة: امنح حسابك دور developer (عديم الأثر عند التكرار). يعيد { enrolled: true, roles }.
GET/developer/accessتحقّق من وصول المطوّر — { developer: true, roles }؛ يسجّلك تلقائيًا عند أول قراءة.
GET/developer/overviewفهرس المنتجات والخطط وحدود المعدّل.
GET/developer/scopesفهرس النطاقات المرجعي (التسمية والوصف والقيم الافتراضية).
GET/developer/summaryأعدادك (المؤسسات، المشاريع، المفاتيح، المفاتيح المفعّلة) وطلبات اليوم.
GET/developer/organizationsعرض مؤسساتك.
POST/developer/organizationsإنشاء مؤسسة (الجسم: name؛ وslug اختياري يُولَّد تلقائيًا).
PATCH/developer/organizations/:idإعادة تسمية مؤسسة.
DELETE/developer/organizations/:idحذف مؤسسة (يشمل مشاريعها ومفاتيحها).
GET/developer/projects?organizationId=…عرض المشاريع.
POST/developer/organizations/:id/projectsإنشاء مشروع داخل مؤسسة (الجسم: name).
POST/developer/projectsإنشاء مشروع (الصيغة المسطّحة — الجسم: name, organizationId).
PATCH/developer/projects/:idإعادة تسمية مشروع.
DELETE/developer/projects/:idحذف مشروع (يشمل مفاتيحه).
GET/developer/api-keys?projectId=…عرض المفاتيح. يُظهر lastFour وscopes وrestrictions وplan والحصص وunlimited وactive والاستخدام الحيّ — ولا يُظهر النص الصريح أبدًا.
POST/developer/api-keysإصدار مفتاح (راجع الحصول على مفتاح). يعيد النص الصريح مرّة واحدة.
GET/developer/api-keys/:id/usageالاستخدام الحيّ للمفتاح: { id, label, active, plan, lastUsedAt, unlimited, minute: { used, limit }, day: { used, limit } }، أي الطلبات في هذه الدقيقة واليوم (بتوقيت UTC) مقابل الحصّة. تكون قيمة limit هي null للمفتاح غير المحدود.
GET/developer/api-keys/:id/usage/monthlyاستخدام الفترة حتى تاريخه لأغراض الفوترة: { id, plan, periodStart, weightedRequests, rawRequests, includedRequests, overageRequests }.
PATCH/developer/api-keys/:idتحديث label أو plan أو scopes أو restrictions أو quotaPerMinute أو quotaPerDay أو active. تُدمَج تغييرات النطاقات فوق نطاقات المفتاح الحالية. والحصّة التي ترسلها دون تغيير تبقى كما هي، حتى لو ضبطتها Navvo فوق سقف الخدمة الذاتية. وفي المفتاح غير المحدود تُتجاهَل quotaPerMinute وquotaPerDay.
POST/developer/api-keys/:id/rotateتوليد سرّ جديد وإبطال القديم. يعيد النص الصريح الجديد مرّة واحدة.
DELETE/developer/api-keys/:idحذف مفتاح نهائيًا.
POST/developer/sandboxتشغيل طلب اختبار للقراءة فقط بهويّة أحد مفاتيحك من جهة الخادم (الجسم: apiKeyId, path, method? GET|POST, body?). يشغّل بيئة الاختبار في البوابة.

التعطيل مقابل الحذف

لإيقاف مفتاح مؤقتًا (وإعادة تشغيله)، اضبط active:

curl -X PATCH "https://navvo.io/api/v1/developer/api-keys/<keyId>" \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'

يُرفَض المفتاح غير المفعّل بالرمز 403 Forbidden حتى تعيد تفعيله. أما DELETE فيزيل المفتاح نهائيًا.

تدوير مفتاح

إذا تسرّب مفتاح أو فُقِد، فقم بتدويره — يولّد ذلك سرًّا جديدًا تمامًا ويُبطِل السابق فورًا، مع الإبقاء على نفس معرّف المفتاح ونطاقاته وحصصه:

curl -X POST "https://navvo.io/api/v1/developer/api-keys/<keyId>/rotate" \
  -H "Authorization: Bearer <accessToken>"

تتضمّن الاستجابة key الجديد بنصّه الصريح — ومرّةً أخرى، يُعرَض مرّة واحدة فقط. انشر السرّ الجديد في تطبيقاتك؛ يتوقّف القديم عن العمل فورًا.

تريد تدويرًا بلا انقطاع؟ أصدر مفتاحًا ثانيًا، وانشره في كل مكان، وتأكّد من انتقال الحركة إليه، ثم احذف (أو عطّل) الأصلي.

تقييد المفتاح

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

القائمةاستخدمها لـتُطابَق مع
referrers: المواقع المسموح بهاالمفاتيح المستخدمة في صفحات الويب (خرائط Navvo، وfetch في المتصفح)ترويسة Origin التي يرسلها المتصفح، أو Referer عند غياب Origin
ips: عناوين IP المسموح بهاالمفاتيح المستخدمة من خوادمكالعنوان الذي يأتي منه الطلب

اضبطهما في بوابة المطورين (مفاتيح API ← تعديل)، أو عبر الواجهة البرمجية:

curl -X PATCH "https://navvo.io/api/v1/developer/api-keys/<keyId>" \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "restrictions": { "referrers": ["example.com", "*.example.com", "localhost:3000"] } }'

المواقع. اكتب اسم المضيف، مع منفذ اختياري: example.com أو app.example.com أو localhost:3000. يشمل *.example.com كل النطاقات الفرعية لكنه لا يشمل example.com نفسه، فاذكر الاثنين إن احتجت إليهما. يُقبَل البروتوكول أو المسار ثم يُحذف (https://example.com/* يُحفَظ بصيغة example.com). وعند عدم ذكر منفذ يُقبَل أي منفذ. يُرفَض الطلب الذي لا يذكر أي موقع، أي الطلب الخالي من Origin وReferer معًا، مثل الطلب الآتي من خادم، أو من متصفح تحذف إعدادات الخصوصية فيه الترويستين.

عناوين IP. اكتب عناوين أو نطاقات CIDR، بصيغة IPv4 أو IPv6: 203.0.113.7 أو 198.51.100.0/24 أو 2001:db8::/32.

تتّسع كل قائمة لـ 50 عنصرًا كحدّ أقصى. وفي طلب PATCH:

  • القائمة التي لا ترسلها تحتفظ بعناصرها؛
  • [] تفرغ القائمة؛
  • "restrictions": null يزيل القائمتين معًا.

يُرفَض العنصر غير الصالح بالرمز 400 وتذكره الرسالة باسمه، ولا يُحذف أي عنصر بصمت. وتتضمّن كل استجابة تخصّ مفتاحًا الحقل restrictions بقائمتيه، وتكونان فارغتين إذا لم يكن المفتاح مقيّدًا.

يعيد الطلب المرفوض الرمز 403 مع code، ومعه الموقع أو عنوان IP الذي جاء منه الطلب، لتعرف ما الذي يجب إضافته:

{
  "statusCode": 403,
  "error": "Forbidden",
  "code": "KEY_WEBSITE_NOT_ALLOWED",
  "message": "This API key is not allowed from this website",
  "details": { "website": "copycat.example" }
}
codeالمعنى
KEY_WEBSITE_NOT_ALLOWEDللمفتاح مواقع مسموح بها، وجاء الطلب من موقع آخر أو لم يذكر أي موقع (وعندها تكون قيمة details.website هي null).
KEY_IP_NOT_ALLOWEDللمفتاح عناوين IP مسموح بها، وجاء الطلب من عنوان آخر (details.ip).

تُفحَص القيود قبل النطاقات والحصّة، فلا يُحتسب الطلب المرفوض من حصّة المفتاح. أما بيئة الاختبار في البوابة فتعمل على خوادم Navvo نيابةً عنك ولا تطبّق هذه القيود.

يمنع تقييد المواقع المواقعَ الأخرى من استخدام مفتاح نُسخ من صفحاتك، لأن المتصفح هو من يضبط Origin وReferer بنفسه. لكنه لا يجعل المفتاح سرًّا: فالنص البرمجي الذي يعمل خارج المتصفح يستطيع إرسال أي ترويسة. خصّص للتكامل من جهة الخادم مفتاحًا مستقلًّا، وقيّده بعنوان IP، وأبقِه خارج الشيفرة التي تعمل لدى العميل.

الأخطاء

الحالةالمعنى
401 Unauthorizedلم يُقدَّم أي مفتاح حيث يكون مطلوبًا، أو المفتاح المُرسَل غير معروف (لم يُصدَر قط، أو جرى تدويره).
403 Forbiddenالمفتاح معطَّل، أو يفتقد النطاق المطلوب، أو يُستخدم من موقع أو عنوان IP غير مسموح به. ويُعاد أيضًا مع code بقيمة QUOTA_EXCEEDED عندما يتجاوز المفتاح حصّته أو الحدّ لكل عنوان IP (ولا يحدث هذا أبدًا للمفتاح غير المحدود).
429 Too Many Requestsأرسل عنوان IP الخاص بك طلبات كثيرة جدًّا إلى نقطة نهاية واحدة (code بقيمة RATE_LIMITED). انتظر الثواني المذكورة في Retry-After. راجع حدود المعدّل.
كل مفتاح مُقدَّم يُتحقَّق منه — ويُحاسَب على نطاقاته وحصّته. إذا أرسلت مفتاح واجهة (في الترويسة أو كمعامل استعلام) فيجب أن يكون مفتاحًا حقيقيًا نشطًا: المفتاح غير المعروف أو المُدوَّر يعيد 401 على كل نقطة نهاية، والمفتاح المعطَّل يعيد 403. ويُرفَض أيضًا بالرمز 401 معامل المفتاح الموجود لكنه فارغ (مسافات فقط) أو المُرسَل أكثر من مرة، أما api_key= الفارغ تمامًا فيُعدّ كأن لا مفتاح. وإلى جانب ذلك، يجب أن يحمل المفتاح المُقدَّم النطاق الذي تتطلّبه نقطة النهاية، وأن يكون ضمن حصّته، وأن يُستخدم من موقع أو عنوان IP يسمح به. فالمفتاح المحدود النطاق أو المستنفِد لحصّته أو المقيَّد يعيد 403 بدلًا من التراجع إلى الوصول المجهول، حتى في عمليات النشر التي يكون فيها فرض المفاتيح متساهلًا عدا ذلك. لذا يسري التدوير أو التعطيل من بوابة المطورين فورًا.

راجع الأخطاء لأجسام الاستجابات وحدود المعدّل لتفاصيل الحصص.

Copyright © 2026