> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# نقطة نهاية الرمز المميز: استبدال الرمز وتحديثه | Didit

> في واجهة المصادقة من Didit، يستبدل POST /token/ رمز تفويض PKCE أو يدوّر رمز التحديث. إعادة استخدام رمز التحديث تُلغي الجلسة.

> [!WARNING]
>
> المصادقة ميزة جديدة. تُقدَّم نقاط endpoint هذه من قِبل مُصدِر تطبيقك، مثل `https://<name>.auth.didit.me`، ولا تقبل أبداً مفتاح API الخاص بـ Didit.

رمز التحديث يعمل مرة واحدة فقط. إرسال رمز تحديث سبق استخدامه مرة أخرى يُلغي الجلسة بأكملها، لذا شغّل عملية تحديث واحدة في كل مرة لكل جلسة، واستبدل الرموز الثلاثة معاً. راجع [رموز التحديث](https://docs.didit.me/ar/authentication/tokens-and-jwks.md#تحديث-الرموز).


## OpenAPI

````yaml ar/openapi-authentication.json POST /token/
openapi: 3.0.3
info:
  title: Didit Authentication API
  version: 1.0.0
  description: >-
    تُعد هذه endpoints المخصصة للخادم لـ Didit Authentication، وهو منتج تسجيل
    الدخول للمستخدمين النهائيين لتطبيقك. ميزة Authentication **جديدة** وتصل إلى
    الإنتاج في إصدار 2026-11-01.


    ## عنوان URL الأساسي


    كل تطبيق هو جهة إصدار OpenID Connect خاصة به، ويتم تقديم كل endpoint أدناه
    في المسار الجذري لجهة الإصدار تلك:


    - `https://<name>.auth.didit.me` لتطبيق في بيئة الإنتاج، أو
    `https://<name>.sandbox.auth.didit.me` لتطبيق في البيئة التجريبية.

    - نطاقك المخصص، بمجرد تفعيله. سيحل بعد ذلك محل المضيف الافتراضي كجهة إصدار:
    تذكره tokens الجديدة في `iss`، وتشير إليه آلية discovery ويتغير المفتاح
    القابل للنشر. تفشل access tokens الصادرة تحت المضيف الافتراضي في `/session/`
    و `/step-up/` و `/monitoring-token/` حتى يتم تجديدها.


    بيئة الإنتاج والبيئة التجريبية هما تطبيقان منفصلان، وبالتالي فهما جهتا إصدار
    منفصلتان بمفاتيح منفصلة. المفتاح القابل للنشر هو `pk_live_` (للإنتاج) أو
    `pk_test_` (للبيئة التجريبية) متبوعاً بترميز base64url غير المبطن لجهة
    الإصدار، دون شرطة مائلة لاحقة: قم بفك ترميزه للعثور على جهة الإصدار. إنه
    معرّف عام، وليس بيانات اعتماد.


    يتم أيضاً تقديم نفس endpoints بتنسيق JSON ضمن
    `https://apx.didit.me/auth/v2/authentication/{application_id}/`. تذكر tokens
    دائماً جهة الإصدار المذكورة أعلاه، أياً كان العنوان الذي أصدرها.


    ## بيانات الاعتماد


    لا تقبل هذه الـ endpoints مطلقاً مفتاح API الخاص بك من Didit أو token لوحة
    التحكم.


    - لا تتطلب Discovery و JWKS و `POST /token/` أي بيانات اعتماد. العملاء
    عامون: لا يوجد سر للعميل (client secret)، ورمز التفويض مرتبط بمتحقق PKCE
    الخاص به (`S256`). يمثل `client_id` معرّف التطبيق الخاص بك.

    - تتطلب `/session/` و `/step-up/` و `/monitoring-token/` الـ access token
    الخاص بالشخص: `Authorization: Bearer <access_token>`. يُحتسب كل استدعاء ناجح
    كنشاط في الجلسة، مما يعيد تشغيل مهلة الخمول للجلسة.


    ## نصوص الطلبات


    يقبل كل endpoint يتلقى نص طلب كلاً من تنسيقات JSON والترميز كنموذج
    (form-encoded) ومتعدد الأجزاء (multipart). يسرد هذا المستند تنسيق JSON،
    بالإضافة إلى form-encoded للطلب `POST /token/` كما يرسله عملاء OAuth. يحصل
    الحقل الذي لا يقبله الـ endpoint على `400 {"<field>": "unknown_field"}`.


    ## Tokens


    - **Access token**: رمز JWT بتشفير ES256 مع الرأس `typ: at+jwt`، صالح لمدة 5
    دقائق على الأكثر ولا يتجاوز أبداً مدة جلسته. المطالبات: `AccessTokenClaims`.

    - **ID token**: رمز JWT بتشفير ES256 مع الرأس `typ: JWT`. المطالبات:
    `IDTokenClaims`. ولا يُقبل أبداً كـ access token.

    - **Refresh token**: سلسلة عشوائية يتم تدويرها مع كل استخدام. يؤدي إرسال
    refresh token مستخدم بالفعل مرة أخرى إلى إبطال الجلسة.


    تحقق من الـ token باستخدام المفاتيح من `GET /.well-known/jwks.json`: يجب أن
    تكون الخوارزمية `ES256`، ويجب أن يطابق `typ` نوع الـ token، ويجب أن يساوي
    `iss` جهة الإصدار التي قمت بتكوينها و `aud` معرّف تطبيقك. لا يكتشف التحقق
    دون اتصال بالإنترنت الجلسة الملغاة إلا بعد انتهاء صلاحية access token الخاص
    بها؛ بينما يمثل `GET /session/` التحقق الفوري.


    ## الأخطاء


    | نص الاستجابة | الحالة |

    | --- | --- |

    | `{"error": "<code>"}` | أخطاء من `POST /token/`، جميعها بالحالة `400`، في
    بنية نص الاستجابة المحددة في [RFC 6749 section
    5.2](https://www.rfc-editor.org/rfc/rfc6749#section-5.2): `invalid_grant` و
    `invalid_client` و `mfa_required` الخاصة بـ Didit. أخطاء الخدمة:
    `temporarily_unavailable` و `monitoring_unavailable` و
    `monitoring_disabled`. |

    | `{"<field>": ["<message>"]}` أو `{"<field>": "<code>"}` | فشل التحقق من
    صحة أحد حقول الطلب. يشير `non_field_errors` إلى قاعدة تنطبق على عدة حقول،
    ويشير `unknown_field` إلى حقل لا يقبله الـ endpoint. |

    | `{"detail": "<message>"}` | `401` (`invalid_token`) و `403`
    (`origin_not_allowed`) و `404` (تطبيق أو خطوة تصعيد غير معروفة) و `429` (حد
    المعدل). وأيضاً `400` لنص طلب يتعذر تحليله (`JSON parse error - ...`) و
    `405` لطريقة لا يدعمها الـ endpoint و `415` لنوع محتوى `Content-Type` غير
    مدعوم. |


    يحمل الرمز `401` أيضاً الرأس `WWW-Authenticate: Bearer`، ويحمل الرمز `429`
    الرأس `Retry-After` بالثواني.


    هناك حالتا رفض لا تُرجعان بتنسيق JSON. يتم رفض العنوان الذي لا يمثل جهة
    إصدار قبل وصوله إلى هذه الـ endpoints، على سبيل المثال استجابة `404` فارغة
    لاسم `*.auth.didit.me` غير مستخدم. ويتلقى معرّف `step_up_id` الذي لا يطابق
    تنسيق UUID صفحة `404`.


    ## حدود المعدل


    يجب أن يمر الطلب عبر طبقتين.


    **حدود الـ endpoint**، وتُحتسب لكل عنوان IP للعميل، ولكل تطبيق، ولكل
    endpoint:


    - Discovery و JWKS: 1,200 طلب في الدقيقة و 12,000 في الساعة.

    - جميع endpoints الأخرى: 30 طلباً في الدقيقة و 300 في الساعة. يشترك الطلبان
    `GET` و `DELETE /session/` في عداد واحد.


    عند تجاوز الحد: `429 {"detail": "Too many requests from this IP address.
    Please wait before trying again. Expected available in 60 seconds."}`، أو
    `3600 seconds` للحد الساعي.


    **الحماية من البوتات**، على كل طلب `POST` و `DELETE`. وتكون مستودعاتها
    مشتركة بين جميع طلبات `POST` و `DELETE` الخاصة بالتطبيق، بما في ذلك خطوات
    تسجيل الدخول المستضافة، وتتم إعادة ملئها باستمرار:


    - 60 طلباً في الدقيقة لكل عنوان IP للعميل.

    - 30 طلباً في الدقيقة لكل جهاز، للطلبات التي تحدد جهازها، كما تفعل حزم SDK
    للمتصفح والأجهزة الأصلية.

    - 3,000 طلب في الدقيقة للتطبيق بالكامل، عبر جميع عناوين IP. وتسحب عمليات
    تجديد الـ token (`POST /token/` مع `grant_type=refresh_token`) من مستودع خاص
    بها بدلاً من ذلك: 6,000 في الدقيقة للتطبيق بالكامل.


    عند تجاوز سعة المستودع: `429 {"detail": "rate_limited Expected available in
    N seconds."}` (`1 second.` عندما تكون N تساوي 1). يشمل مستودع عنوان IP
    الواحد عدة endpoints، لذا فإن عنواناً واحداً يجمع بين استدعاءات token و
    step-up وتسجيل الخروج يمكنه استنزافه قبل الوصول إلى أي حد خاص بالـ endpoint.
    يحتسب مستودع التطبيق كل عميل للتطبيق، بما في ذلك المتصفحات.


    تجيب كلتا الطبقتين قبل تشغيل الـ endpoint، لذا فإن الطلب الذي تلقى `429` لم
    يتم تنفيذه: أعد المحاولة بعد انقضاء `Retry-After`، بما في ذلك طلبات التجديد.


    ## طلبات المتصفح


    يجب أن يأتي الطلب الذي يحمل الرأس `Origin` من أحد مصادر التطبيق نفسه أو
    مصادره المسموح بها، وإلا سيتلقى `403 origin_not_allowed`. لا ترسل الطلبات
    بين الخوادم الرأس `Origin`.


    ## ما لا يغطيه هذا المستند


    تخدم هذه المسارات الصفحات المستضافة، وحزم SDK للمتصفح والأجهزة الأصلية،
    ووكلاء الذكاء الاصطناعي. وهي ليست جزءاً من عقد الخادم، ولا تستدعيها حزم SDK
    للخادم:


    - خطوات تسجيل الدخول: `POST /authorize/` و `POST /password/` و `/email/*` و
    `/phone/*` و `/password-reset/*` و `/passkeys/*` و `/mfa/*` و `/social/*` و
    `/protection/complete/`.

    - الصفحات المستضافة وعمليات الاستدعاء: `/sign-in` و `/magic` و `/invite` و
    `/reset` و `/verify/` و `/sso/*` و `/wallet/callback/` و `/logo/` وملفات ربط
    التطبيقات الأصلية تحت `/.well-known/`.

    - وصول الوكلاء: `/agents/*` و `/grants/`، بما في ذلك `GET /agents/session/`،
    وهو الفحص المباشر لـ access token الخاص بوكيل الذكاء الاصطناعي. وصول الوكلاء
    ليس جزءاً من هذا الإصدار من العقد.

    - واجهة API لإدارة لوحة التحكم الخاصة بـ Authentication، والتي تتطلب جلسات
    لوحة التحكم.


    لا يتم تسليم أحداث Authentication كـ webhooks حتى الآن، لذا لا يحدد هذا
    المستند أي webhook.
servers:
  - url: https://{issuer}
    description: 'الجهة المصدرة لتطبيقك: مصدر تسجيل الدخول الخاص به.'
    variables:
      issuer:
        default: your-app.auth.didit.me
        description: >-
          مضيف الجهة المصدرة: `<name>.auth.didit.me` (بيئة الإنتاج)، أو
          `<name>.sandbox.auth.didit.me` (البيئة التجريبية)، أو نطاقك المخصص
          النشط.
security: []
tags:
  - name: Issuer
    description: مفاتيح الاكتشاف والتوقيع، للتحقق من token.
  - name: Tokens
    description: منح رمز التفويض ومنح التحديث.
  - name: Sessions
    description: التحقق من الجلسة التابعة لـ token وصول وإنهاؤها.
  - name: Step-ups
    description: التحقق قبل إجراء حساس.
  - name: Monitoring
    description: بيانات اعتماد الجهاز لأحداث مراقبة المعاملات.
paths:
  /token/:
    post:
      tags:
        - Tokens
      summary: تبادل رمز أو تحديث token
      description: >-
        endpoint الخاص بالـ token، لكلا نوعي المنح.


        - يستبدل `authorization_code` الرمز الذي استلمه `redirect_uri` الخاص بك
        بـ access token وID token وrefresh token. يعمل الرمز لمرة واحدة، خلال 60
        ثانية، مع قيمة التحقق الخاصة بـ PKCE ونفس `redirect_uri` الخاص بتسجيل
        الدخول تماماً. عندما يسمح التطبيق بجلسة واحدة لكل شخص، ينهي الاستبدال
        جلسات الشخص الأخرى.

        - يُرجع `refresh_token` كلاً من access token وID token وrefresh token
        جديد، ويتوقف refresh token الذي أرسلته عن العمل. **إعادة إرسال refresh
        token مستخدم بالفعل تلغي الجلسة** وتُرجع `invalid_grant`، لذا قم بتشغيل
        عملية تحديث واحدة في كل مرة للجلسة واستبدل الـ tokens الثلاثة معاً. بعد
        فشل التحديث بالرمز `400`، أو عدم تلقي أي إجابة، ابدأ تسجيل الدخول مجدداً
        بدلاً من إعادة المحاولة: إعادة المحاولة بعد تحديث نجح بالفعل تُعد إعادة
        استخدام. يُجاب عن الخطأ `429` قبل تشغيل التحديث، لذا من الآمن إعادة
        المحاولة بعد `Retry-After`. الرمز `503` يعني أن التحديث لم يحدث وأن
        refresh token لا يزال يعمل: أعد محاولته مع استخدام التراجع التدريجي
        (backoff).


        يمكن أن يكون نص الطلب بتنسيق JSON أو مشفّراً بترميز النموذج.
      operationId: authentication_token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
            examples:
              AuthorizationCode:
                summary: تبادل رمز التفويض
                value:
                  grant_type: authorization_code
                  code: Vb0bVt4CLlr8ZL0kE5mAxv8gS6R0rW3hYqC1pN7dJ2s
                  code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
                  redirect_uri: https://app.example.com/auth/callback
              RefreshToken:
                summary: تحديث رموز token
                value:
                  grant_type: refresh_token
                  refresh_token: >-
                    N4yZTl6y24YKYq77X_SOrBn1q2Lit81WBQMOay7dq_IVfTnxyY8ZGcJk-6-fcmWW
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenRequest'
      responses:
        '200':
          description: رموز token جديدة للجلسة.
          headers:
            Cache-Control:
              description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
              schema:
                type: string
                example: no-store
            Pragma:
              description: دائماً `no-cache`.
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
              examples:
                Tokens:
                  summary: token لجلسة جديدة
                  value:
                    access_token: >-
                      eyJhbGciOiJFUzI1NiIsImtpZCI6ImtfOHNKMmRRdlgwbkxyNVRmWWIzSGtQdyIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJodHRwczovL3lvdXItYXBwLmF1dGguZGlkaXQubWUiLCJhdWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQiLCJzdWIiOiIxYzlkOGI4OC0xYmZmLTQzZDEtYWQ3YS04OGIyYmMwMDI0ZTkiLCJzaWQiOiJjOWFiZjZjYy0yZDY0LTRiZjItYjMxZS1hNGQwOWEwNzBhYjEiLCJqdGkiOiJSZ3F1NzE3OWUtbGhKMGJ2VmVELVlnIiwiaWF0IjoxNzkyMjMzNjc0LCJleHAiOjE3OTIyMzM5NzQsInZlbmRvcl9kYXRhIjoidXNlci00MiIsIm9yZyI6bnVsbCwidmVyaWZpZWQiOnt9LCJhbXIiOlsicGFzc3dvcmQiXSwiYWN0IjpudWxsLCJjbGllbnRfaWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQifQ.AxrqN8Pm-Op-3OayZk8HcvlFQZhozRiOvQ0SgQsGgrz4UNeJlUEeSlq9B8WcYUuM8naRaY5kQt_TUofnsYcyYQ
                    id_token: >-
                      eyJhbGciOiJFUzI1NiIsImtpZCI6ImtfOHNKMmRRdlgwbkxyNVRmWWIzSGtQdyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3lvdXItYXBwLmF1dGguZGlkaXQubWUiLCJhdWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQiLCJzdWIiOiIxYzlkOGI4OC0xYmZmLTQzZDEtYWQ3YS04OGIyYmMwMDI0ZTkiLCJzaWQiOiJjOWFiZjZjYy0yZDY0LTRiZjItYjMxZS1hNGQwOWEwNzBhYjEiLCJqdGkiOiJNTHRPNHM4SHItQnJrcDd2NTlPV0Z3IiwiaWF0IjoxNzkyMjMzNjc0LCJleHAiOjE3OTIyMzM5NzQsInZlbmRvcl9kYXRhIjoidXNlci00MiIsIm9yZyI6bnVsbCwidmVyaWZpZWQiOnt9LCJhbXIiOlsicGFzc3dvcmQiXSwiYWN0IjpudWxsLCJhdXRoX3RpbWUiOjE3OTIyMzM2NzQsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJlbWFpbCI6InBlcnNvbkBleGFtcGxlLmNvbSIsIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.avhfDFp_aUV5_1ssYzwDcIA7H6Waf19P0bn5GCg25FhLIZBGIlwc8HiUPGj1j26r21OkP4FQnS_jM1Ho3dHtKQ
                    refresh_token: >-
                      N4yZTl6y24YKYq77X_SOrBn1q2Lit81WBQMOay7dq_IVfTnxyY8ZGcJk-6-fcmWW
                    token_type: Bearer
                    expires_in: 299
                    session_id: c9abf6cc-2d64-4bf2-b31e-a4d09a070ab1
        '400':
          description: >-
            فشل التفويض. `invalid_grant`: الرمز أو رمز التحديث غير معروف أو
            مستخدم أو منتهي الصلاحية؛ أو أن مُحقق PKCE أو `redirect_uri` لا
            يتطابق، أو أن `redirect_uri` لم يعد مسجلاً؛ أو تم حظر الشخص أو لم
            يعد بريده الإلكتروني موثقاً؛ أو انتهت الجلسة أو لم تعد تستوفي سياسة
            MFA الخاصة بك؛ أو، بالنسبة للرمز، قمت بإيقاف طريقة تسجيل الدخول التي
            أتى منها. لا يؤدي إيقاف طريقة ما إلى إيقاف تحديث الجلسات التي بدأت
            بالفعل بواسطتها. `invalid_client`: المعرّف `client_id` ليس معرّف
            تطبيقك. `mfa_required`: تسجيل الدخول لم يستوفِ سياسة MFA الخاصة بك.
            تحدد أخطاء الحقول الحقل المفقود أو غير الصالح. يحصل النص الأساسي
            الذي يتعذر تحليله على رسالة `detail`.
          headers:
            Cache-Control:
              description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
              schema:
                type: string
                example: no-store
            Pragma:
              description: دائماً `no-cache`.
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/OAuthError'
                  - $ref: '#/components/schemas/FieldErrors'
                  - $ref: '#/components/schemas/Detail'
              examples:
                InvalidGrant:
                  summary: تم رفض الرمز أو رمز التحديث
                  value:
                    error: invalid_grant
                InvalidClient:
                  summary: قيمة client_id خاطئة
                  value:
                    error: invalid_client
                MfaRequired:
                  summary: لم يتم استيفاء سياسة MFA
                  value:
                    error: mfa_required
                MissingFields:
                  summary: منحة بدون حقولها المطلوبة
                  value:
                    non_field_errors:
                      - invalid_request
                UnknownGrant:
                  summary: ‏grant_type غير مدعوم
                  value:
                    grant_type:
                      - '"password" is not a valid choice.'
                UnknownField:
                  summary: حقل لا يقبله الـ endpoint
                  value:
                    foo: unknown_field
                MalformedBody:
                  summary: نص JSON يتعذر تحليله
                  value:
                    detail: >-
                      JSON parse error - Expecting property name enclosed in
                      double quotes: line 1 column 2 (char 1)
        '403':
          $ref: '#/components/responses/OriginNotAllowed'
        '404':
          $ref: '#/components/responses/ApplicationNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/TemporarilyUnavailable'
      security:
        - {}
components:
  schemas:
    TokenRequest:
      description: >-
        واحد من المنحين الاثنين، يتم اختياره عبر `grant_type`. يقبل endpoint
        حقول كلا المنحين ويتحقق من صحة كل حقل يتلقاه، لذا فإن التجديد الذي يحمل
        أيضاً `code_verifier` غير صالح يحصل على خطأ في الحقل. أرسل حقول المنح
        الخاص بك فقط؛ أي حقل آخر يتلقى `unknown_field`.
      oneOf:
        - $ref: '#/components/schemas/AuthorizationCodeGrantRequest'
        - $ref: '#/components/schemas/RefreshTokenGrantRequest'
      discriminator:
        propertyName: grant_type
        mapping:
          authorization_code: '#/components/schemas/AuthorizationCodeGrantRequest'
          refresh_token: '#/components/schemas/RefreshTokenGrantRequest'
    TokenResponse:
      type: object
      description: token لجلسة واحدة. استبدل الثلاثة معًا بعد التحديث.
      required:
        - access_token
        - id_token
        - refresh_token
        - token_type
        - expires_in
        - session_id
      properties:
        access_token:
          type: string
          description: >-
            ES256 JWT برأس `typ: at+jwt`. أرسله بتنسيق `Authorization: Bearer
            <access_token>`. المطالبات: `AccessTokenClaims`.
          example: >-
            eyJhbGciOiJFUzI1NiIsImtpZCI6ImtfOHNKMmRRdlgwbkxyNVRmWWIzSGtQdyIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJodHRwczovL3lvdXItYXBwLmF1dGguZGlkaXQubWUiLCJhdWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQiLCJzdWIiOiIxYzlkOGI4OC0xYmZmLTQzZDEtYWQ3YS04OGIyYmMwMDI0ZTkiLCJzaWQiOiJjOWFiZjZjYy0yZDY0LTRiZjItYjMxZS1hNGQwOWEwNzBhYjEiLCJqdGkiOiJSZ3F1NzE3OWUtbGhKMGJ2VmVELVlnIiwiaWF0IjoxNzkyMjMzNjc0LCJleHAiOjE3OTIyMzM5NzQsInZlbmRvcl9kYXRhIjoidXNlci00MiIsIm9yZyI6bnVsbCwidmVyaWZpZWQiOnt9LCJhbXIiOlsicGFzc3dvcmQiXSwiYWN0IjpudWxsLCJjbGllbnRfaWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQifQ.AxrqN8Pm-Op-3OayZk8HcvlFQZhozRiOvQ0SgQsGgrz4UNeJlUEeSlq9B8WcYUuM8naRaY5kQt_TUofnsYcyYQ
          x-didit-jwt:
            header: '#/components/schemas/AccessTokenHeader'
            claims: '#/components/schemas/AccessTokenClaims'
        id_token:
          type: string
          description: >-
            ES256 JWT برأس `typ: JWT`، ليقرأ تطبيقك من قام بتسجيل الدخول. لا
            ترسله أبداً كـ token للوصول. المطالبات: `IDTokenClaims`.
          example: >-
            eyJhbGciOiJFUzI1NiIsImtpZCI6ImtfOHNKMmRRdlgwbkxyNVRmWWIzSGtQdyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3lvdXItYXBwLmF1dGguZGlkaXQubWUiLCJhdWQiOiI3YjBhNmMyZS0zZjQxLTRjOWEtOGQ1NS0xZTJmM2E0YjVjNmQiLCJzdWIiOiIxYzlkOGI4OC0xYmZmLTQzZDEtYWQ3YS04OGIyYmMwMDI0ZTkiLCJzaWQiOiJjOWFiZjZjYy0yZDY0LTRiZjItYjMxZS1hNGQwOWEwNzBhYjEiLCJqdGkiOiJNTHRPNHM4SHItQnJrcDd2NTlPV0Z3IiwiaWF0IjoxNzkyMjMzNjc0LCJleHAiOjE3OTIyMzM5NzQsInZlbmRvcl9kYXRhIjoidXNlci00MiIsIm9yZyI6bnVsbCwidmVyaWZpZWQiOnt9LCJhbXIiOlsicGFzc3dvcmQiXSwiYWN0IjpudWxsLCJhdXRoX3RpbWUiOjE3OTIyMzM2NzQsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJlbWFpbCI6InBlcnNvbkBleGFtcGxlLmNvbSIsIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.avhfDFp_aUV5_1ssYzwDcIA7H6Waf19P0bn5GCg25FhLIZBGIlwc8HiUPGj1j26r21OkP4FQnS_jM1Ho3dHtKQ
          x-didit-jwt:
            header: '#/components/schemas/IDTokenHeader'
            claims: '#/components/schemas/IDTokenClaims'
        refresh_token:
          type: string
          description: >-
            للاستخدام لمرة واحدة. وهو صالح حتى انتهاء الجلسة، وتُرجع كل عملية
            تحديث رابطاً جديداً.
          example: N4yZTl6y24YKYq77X_SOrBn1q2Lit81WBQMOay7dq_IVfTnxyY8ZGcJk-6-fcmWW
        token_type:
          type: string
          enum:
            - Bearer
        expires_in:
          type: integer
          minimum: 0
          maximum: 300
          description: >-
            عدد الثواني حتى انتهاء صلاحية رمز الوصول: بحد أقصى 300، وتكون أقل
            عندما تنتهي الجلسة في وقت أقرب.
          example: 299
        session_id:
          type: string
          format: uuid
          description: الجلسة التي تنتمي إليها هذه الـ token، وهي نفس قيمة المطالبة `sid`.
          example: c9abf6cc-2d64-4bf2-b31e-a4d09a070ab1
    OAuthError:
      title: OAuth error
      type: object
      description: خطأ OAuth (القسم 5.2 من RFC 6749) أو خطأ في الخدمة.
      required:
        - error
      properties:
        error:
          type: string
          example: invalid_grant
    FieldErrors:
      title: Field errors
      type: object
      description: >-
        أخطاء التحقق حسب الحقل. تكون القيمة عبارة عن قائمة من الرسائل، أو رمز
        واحد (`unknown_field`، `invalid_redirect_uri`). يحتوي `non_field_errors`
        على القواعد المطبقة عبر حقول متعددة.
      additionalProperties:
        oneOf:
          - type: string
          - type: array
            items:
              type: string
    Detail:
      type: object
      required:
        - detail
      properties:
        detail:
          type: string
          example: invalid_token
    AuthorizationCodeGrantRequest:
      title: Authorization code grant
      type: object
      description: >-
        تبادل رمز التفويض الناتج عن إعادة التوجيه للحصول على token. يعمل الرمز
        لمرة واحدة، لمدة 60 ثانية.
      required:
        - grant_type
        - code
        - code_verifier
        - redirect_uri
      properties:
        grant_type:
          type: string
          enum:
            - authorization_code
        code:
          type: string
          maxLength: 128
          description: >-
            معامل الاستعلام `code` الذي تلقاه `redirect_uri` الخاص بك. تحقق من
            `state` للاستدعاء قبل استبداله.
          example: Vb0bVt4CLlr8ZL0kE5mAxv8gS6R0rW3hYqC1pN7dJ2s
        code_verifier:
          type: string
          minLength: 43
          maxLength: 128
          pattern: ^[A-Za-z0-9._~-]{43,128}$
          description: >-
            متحقّق PKCE الذي كانت تجزئة S256 الخاصة به هي `code_challenge`
            لتسجيل الدخول.
          example: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
        redirect_uri:
          type: string
          maxLength: 2048
          description: >-
            عنوان `redirect_uri` الدقيق الذي بدأ به تسجيل الدخول. ويجب أن يظل
            أحد عناوين URI لإعادة التوجيه الخاصة بالتطبيق.
          example: https://app.example.com/auth/callback
        client_id:
          type: string
          maxLength: 64
          description: >-
            اختياري. عند إرساله، يجب أن يطابق معرّف التطبيق الخاص بك، وإلا سيفشل
            الطلب مع `invalid_client`.
          example: 7b0a6c2e-3f41-4c9a-8d55-1e2f3a4b5c6d
        scope:
          type: string
          maxLength: 512
          description: >-
            اختياري ومقبول من عملاء OpenID Connect القياسيين. لا يؤدي أبداً إلى
            توسيع نطاق ما منحه تسجيل الدخول.
          example: openid email
    RefreshTokenGrantRequest:
      title: Refresh token grant
      type: object
      description: >-
        استبدال token التحديث بـ token وصول، وtoken تعريف، وtoken تحديث جديدة.
        يعمل token التحديث لمرة واحدة فقط: يؤدي إرساله مجدداً إلى إلغاء الجلسة،
        لذا شغّل عملية تحديث واحدة في كل مرة للجلسة.
      required:
        - grant_type
        - refresh_token
      properties:
        grant_type:
          type: string
          enum:
            - refresh_token
        refresh_token:
          type: string
          maxLength: 128
          description: رمز `refresh_token` من استجابة token السابقة.
          example: N4yZTl6y24YKYq77X_SOrBn1q2Lit81WBQMOay7dq_IVfTnxyY8ZGcJk-6-fcmWW
        client_id:
          type: string
          maxLength: 64
          description: >-
            اختياري. عند إرساله، يجب أن يطابق معرّف التطبيق الخاص بك، وإلا سيفشل
            الطلب مع `invalid_client`.
          example: 7b0a6c2e-3f41-4c9a-8d55-1e2f3a4b5c6d
        scope:
          type: string
          maxLength: 512
          description: >-
            اختياري ومقبول من عملاء OpenID Connect القياسيين. لا يؤدي التحديث
            أبداً إلى توسيع نطاق ما تحتفظ به الجلسة.
          example: openid email
  responses:
    OriginNotAllowed:
      description: >-
        تضمن الطلب رأس `Origin` ليس خاصاً بالتطبيق ولا يندرج ضمن أصول التطبيق
        المسموح بها. لا ترسل طلبات الخادم أي `Origin`.
      headers:
        Cache-Control:
          description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: دائماً `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            OriginNotAllowed:
              summary: الأصل غير مسموح به
              value:
                detail: origin_not_allowed
    ApplicationNotFound:
      description: >-
        العنوان يتبع تطبيقاً، ولكن المصادقة غير مفعّلة له؛ وعلى العنوان
        `apx.didit.me`، يكون معرّف التطبيق غير معروف. يتم رفض العنوان الذي لا
        يتبع أي تطبيق قبل أن يصل إلى endpoint، وتلك الاستجابة لا تكون بتنسيق
        JSON.
      headers:
        Cache-Control:
          description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: دائماً `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            ApplicationNotFound:
              summary: تطبيق غير معروف
              value:
                detail: No Configuration matches the given query.
    RateLimited:
      description: >-
        طلبات كثيرة جداً من عنوان IP هذا لهذا الـ endpoint، أو في حالة `POST` أو
        `DELETE`، فإن وعاء الحماية من البوتات فارغ. لم يتم تشغيل أي شيء: انتظر
        عدد الثواني المحدد في `Retry-After`، ثم أعد المحاولة.
      headers:
        Retry-After:
          description: عدد الثواني الواجب انتظارها قبل إعادة المحاولة.
          schema:
            type: integer
            example: 60
        Cache-Control:
          description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: دائماً `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            RateLimited:
              summary: حد الـ endpoint
              value:
                detail: >-
                  Too many requests from this IP address. Please wait before
                  trying again. Expected available in 60 seconds.
            BotProtection:
              summary: حد الحماية من البوت (POST وDELETE)
              value:
                detail: rate_limited Expected available in 2 seconds.
    TemporarilyUnavailable:
      description: >-
        خدمة يعتمد عليها الطلب غير متوفرة لفترة وجيزة. أعد المحاولة مع التراجع
        التدريجي.
      headers:
        Cache-Control:
          description: 'دائماً `no-store`: لا تقم بتخزين هذه الاستجابة مؤقتاً أبداً.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: دائماً `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
          examples:
            TemporarilyUnavailable:
              summary: إعادة المحاولة لاحقاً
              value:
                error: temporarily_unavailable

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.