إنتقل إلى المحتوى الرئيسي

المصادقة والنطاقات

تتم مصادقة platform API باستخدام مفتاح من مؤسستك. ويتوفر بشكلين — المؤسسة نفسها، والنطاقات نفسها، وruntime مختلف:

FormCredentialSent as
Server (backend)kld_sk_live_…Authorization: Bearer … أو X-Api-Key
Publishable (browser)kld_pk_live_…يتم تبديله بواسطة SDK بجلسة قصيرة العمر؛ ولا يُرسل أبدًا كـ raw bearer
Authorization: Bearer kld_sk_live_…
# or
X-Api-Key: kld_sk_live_…

Server keys هي bearer الذي ترسله من backend الخاص بك مع كل request. أما Publishable keys فهي للمتصفح: يقوم SDK بتبديل المفتاح وقت التشغيل بـ session token قصير العمر ومرتبط بالـ origin، ولذلك لا يصبح publishable key نفسه credential دائمًا في source الخاص بالصفحة. ويتم رفض publishable key إذا تم تقديمه مباشرة كـ bearer — استخدمه عبر SDK. ولا يحصل server key على أي CORS grant، لذلك لا يمكن للصفحة مطلقًا قراءة response تم إنشاؤه باستخدامه — لكن CORS لا يستطيع منع request من مغادرة المتصفح، ولذلك يكون server key الذي تم وضعه في page source قد تسرب بالفعل بحلول الوقت الذي يرفض فيه API الطلب. ويرفض SDK مفاتيح kld_sk_… عند mount لهذا السبب تحديدًا: احتفظ دائمًا بـ server keys على server-side.

تستمر مفاتيح kld_live_… القديمة الحالية في العمل كـ direct bearer في كلا المكانين.

النطاقات

يحمل المفتاح capability scopes؛ وتتطلب كل route family واحدًا منها:

ScopeRoute familyUsed by
ai/inference-api/b2b/v1/chat/*, /retrieval/*chat embed
design/inference-api/b2b/v1/design/*editor embed
mapsdesigned basemapsthe tile embed
vendor(modifier, not a route)the chat embed, on your own data

بشكل افتراضي، يتم إنشاء مفتاح Pro/Enterprise باستخدام ai وdesign وmaps. وتقتصر مفاتيح خطة Free على maps + منتج tile؛ راجع الحصول على مفتاح API للاطلاع على جدول plan × scope × product المعتمد.

Effective admission = stored key × current tier. تعيد عملية runtime session-exchange حساب admission في كل call، ولذلك فإن مفتاح Pro-tier الذي تم تخفيضه إلى Free لا ينشئ إلا tile sessions من تلك اللحظة — حتى إذا كان المفتاح المخزن لا يزال يحمل ai وdesign ضمن قيوده. ويميز rejection subcode بين الحالتين:

  • insufficient_scope — المفتاح لم يمتلك capability من قبل.
  • tier_capability_not_allowed — المفتاح كان يمتلكها، لكن current tier لم يعد يسمح بها. قم بترقية الخطة لاستعادتها.

تعني قيمة allowed_products الفارغة في المفتاح المخزن كل المنتجات (وليس لا شيء). ويستمر tier في تضييق هذه المجموعة إلى ما تسمح به الخطة.

vendor — اطلبه عمدًا، وفقط حيث تحتاج إليه

vendor ليس route gate. فهو لا يسمح بالـ request أو يرفضه؛ بل يحدد ما إذا كان AI chat يمكنه الرجوع إلى بيانات vendor التي رفعتها مؤسستك عند الإجابة. كل scope آخر يجيب عن سؤال "هل يمكن لهذا المفتاح استدعاء هذا endpoint"؛ أما vendor فيجيب عن "هل يمكن لهذا المفتاح التحدث بالاعتماد على بياناتنا الداخلية".

ولذلك فهو لا يُضمّن افتراضيًا مطلقًا — اطلبه صراحةً عند mint:

{ "name": "our-site-widget", "scopes": ["ai", "vendor"] }

المفتاح الذي يحمل vendor هو القرار الأمني بالكامل. chat embed هو browser widget: فهو يبدل publishable key بجلسة قصيرة العمر، ولذلك فإن المفتاح الذي يحتوي على vendor يوجد بالضرورة في صفحة عامة. وهذا مناسب للبيانات التي لا تمانع في عرضها لكل زائر للموقع — مثل قائمة العقارات، وساعات العمل، والأسعار العامة. لكنه غير مناسب لأي شيء لا تريد نشره. إن origin allowlist التي تحمي عملية exchange هي convention خاصة بالمتصفح، وليست confidentiality boundary: فالجهة التي تضبط header Origin الخاص بها لن يمنعها ذلك.

لذلك:

  • مفتاح واحد لكل surface. لا ينبغي لموقع marketing وصفحة demo وتطبيقك الموجه للعملاء مشاركة المفتاح نفسه. فقط surface الذي يجب أن يجيب من بياناتك يحصل على vendor.
  • لا تضع أبدًا rate sheet أو cost basis أو أي شيء غير منشور خلف publishable key. إذا كان من المحرج أن تظهر الإجابة في صفحة عامة، فلا ينبغي أن تكون البيانات ضمن vendor-scoped embed.
  • يتم تضييق sessions إلى product الخاص بها، ولذلك فإن session خاصة بـ tile أو viewer لا تحمل vendor أبدًا حتى إذا كان parent key يحملها.

لسحبها، قم بتعديل scopes الخاصة بالمفتاح أو revoke للمفتاح — ويسري كلاهما عند الـ request التالي، بما في ذلك sessions الموجودة بالفعل. ولا يتم تأجيل السحب حتى expiry الخاصة بالجلسة.

401 مقابل 403

هما مختلفان عمدًا:

  • 401 Unauthorized — مفتاح مفقود / غير صالح / revoked / expired. أعد التحقق من قيمة المفتاح وأنه غير revoked. وكذلك publishable_requires_session عندما يتم إرسال publishable key كـ raw bearer.
  • 403 Forbidden — المفتاح موجود لكنه غير مسموح له هنا. من أشهر subcodes: insufficient_scope (لم يمتلكها أصلًا)، tier_capability_not_allowed (كان يمتلكها لكن tier لم يعد يسمح بها)، session_origin_mismatch، ip_not_allowed (server keys)، server_key_in_browser، product_not_allowed.

كلاهما fail closed: المفتاح الذي لا يحتوي على scopes يُرفض في كل مكان.

Session tokens

تبدو session التي يبدل SDK الـ publishable key بها هكذا:

kld_sess_{env}_{jwt}

على سبيل المثال kld_sess_live_eyJhbGciOi…. ويتم تقديمها في runtime calls كـ Authorization: Bearer أو X-Api-Key. Default TTL هو 900 ثانية (15 دقيقة)؛ والحد الأقصى من server هو 30 دقيقة. يتم تضييق sessions إلى product الذي تم mint لها، وكل request يعيد قراءة live policy الخاصة بالـ parent key.

السحب فوري؛ أما منح الصلاحية فليس كذلك. الاتجاهان غير متماثلين عمدًا، ويعملان وفق fail closed:

Change to the parent keyEffect on a session already in flight
Revoked or deletedيتم الرفض في الـ request التالي
A scope removedتختفي في الـ request التالي
Plan downgradedترفض capabilities المقيدة بالـ tier في الـ request التالي
Rate limit or monthly cap set to a new valueيسري في الـ request التالي
A scope added, plan upgraded, or a limit lifted entirelyغير مرئي — قم بإنشاء session جديدة

لا يمكن للـ session إلا أن تضيق مقارنةً بالـ parent، ولا يمكنها أبدًا توسيع scopes التي تم mint بها، ولذلك يتطلب grant جديد exchange جديدًا. Sessions قصيرة (الافتراضي 15 دقيقة) تحديدًا لكي تكون هذه الفجوة صغيرة.

راجع Errors للاطلاع على جدول status الكامل.