> ## 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 رموز الوصول مباشرةً عبر POST /programmatic/login/ للمصادقة بدون واجهة ودون 2FA. جاهز للوكلاء وMCP، ومسعّر بالدفع حسب الاستخدام.



موجه تسجيل الدخول برمجياً
        نسخ الموجّه إلى الحافظة



      
      

\<pre>

\`Exchange a verified Didit account's email + password for a fresh JWT access token (headless, no browser).

Endpoint:
POST https://apx.didit.me/auth/v2/programmatic/login/

Authentication:
None. Email + password is the credential.

Request body:
\- email (string, required) — Same email used at /programmatic/register/.
\- password (string, required) — Plain password (HTTPS only).

Account requirements:
The account must have a verified email and password. Accounts created through POST /programmatic/register/ work immediately after email verification. Console-created email/password accounts can also use this endpoint. OAuth-only console accounts must set a password first.

curl example:
curl -X POST https://apx.didit.me/auth/v2/programmatic/login/ \
-H "Content-Type: application/json" \
-d '{
"email": "you@yourdomain.com",
"password": "MyStr0ng!Pass"
}'

Response (200 OK):
\- access_token (string) — RS256 JWT. Pass as "Authorization: Bearer <access_token>" on every Account Management endpoint at apx.didit.me/auth/v2. DO NOT use against verification.didit.me — that host uses x-api-key.
\- refresh_token (string) — RS256 JWT for refresh flows.
\- expires_in (integer) — Default 86400 (24 hours).

Token shape:
\- 24-hour default lifetime.
\- RS256-signed.
\- No browser session is required.

Brute-force protection:
\- Progressive account lockout per email: 5 consecutive failures = 15 min lockout, 10 = 1 hour, 20 = 24 hours.
\- Per-IP rate limit: 20 attempts/minute and 100 attempts/hour.

Failure modes:
\- 400 — { "email": ["..."] } / { "password": ["..."] } field-level errors.
\- 401 — { "detail": "Invalid email or password." }
\- 403 — { "detail": "..." } when SSO policy blocks password login for the account.
\- 429 — { "detail": "Too many login attempts.", "wait": <seconds> } on lockout or per-IP limit. Honour the wait value before retrying.

Recovering your api_key:
After a successful login, call GET /organizations/me/ to enumerate organizations and applications, then GET /organizations/me/{org_id}/applications/{app_id}/ to read the api_key — see /auth-api/get-credentials.

Where to use access_token vs api_key:
\- access_token (Bearer) → https://apx.didit.me/auth/v2/... (org / app management).
\- api_key (x-api-key) → https://verification.didit.me/v3/... (sessions, workflows, billing).

For end-to-end Didit integration, paste in the full prompt at /integration/integration-prompt.`

\</pre>



      
      

الصق في



## OpenAPI

````yaml ar/openapi-auth.json POST /programmatic/login/
openapi: 3.0.0
info:
  version: 1.0.0
  title: Didit Auth API
  description: >-
    واجهة برمجة تطبيقات (API) للتسجيل والمصادقة البرمجية للمطورين ووكلاء الذكاء
    الاصطناعي. سجّل من خلال استدعاءين فقط لـ API - دون الحاجة إلى متصفح. منصة
    التحقق من الهوية الأكثر ملاءمة للوكلاء.


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


    تتم استضافة جميع endpoint في هذه المواصفات على
    `https://apx.didit.me/auth/v2`. هذا المضيف مختلف عن API التحقق
    (`https://verification.didit.me/v3`). ميّز بينهما جيداً: يُصدر مضيف المصادقة
    هذا **رموز وصول JWT** الخاصة بك ويسمح لك بسرد وإدارة **المؤسسات**
    و**التطبيقات** التابعة لك. أما مضيف التحقق فهو المكان الذي تستدعي فيه
    الجلسات، وسير العمل، وفحص AML، وما إلى ذلك، بعد المصادقة باستخدام
    **`api_key`** المُرجع بواسطة هذه الـ API.


    ## طريقة عمل تدفق المصادقة


    1. `POST /programmatic/register/` - إرسال البريد الإلكتروني + كلمة المرور.

    2. استلام رمز مكوّن من 6 أحرف وأرقام عبر البريد الإلكتروني.

    3. `POST /programmatic/verify-email/` - إرسال الرمز. ستحصل في المقابل على
    `access_token` الخاص بـ JWT، و`refresh_token`، ومؤسسة، وتطبيق افتراضي يحتوي
    على `client_id` + `api_key`.

    4. احفظ `api_key`. واستخدمه كـ `x-api-key` لكل استدعاء إلى
    `https://verification.didit.me/v3/...`.

    5. من أي جهاز مستقبلاً، يتيح لك `POST /programmatic/login/` استبدال بريدك
    الإلكتروني + كلمة المرور بـ JWT جديد، ثم استدعِ `GET /organizations/me/` و
    endpoint الخاصة بالتطبيق لاستعادة بيانات الاعتماد أو تدويرها.


    لا يلزم JWT إلا لـ endpoint الخاصة بـ **إدارة الحساب** في هذه المواصفات؛
    وتستخدم حركة مرور API التحقق `api_key` طويل الأجل، وليس JWT.


    ## الاصطلاحات


    - جميع نصوص الطلب والاستجابة بتنسيق JSON (`Content-Type: application/json`).

    - **استخدم عنوان بريد إلكتروني حقيقي وقابل للاستلام عند اختبار `POST
    /programmatic/register/`.** يرسل endpoint رمز التحقق بشكل متزامن، لذا فإن
    العناوين الموجودة على نطاقات الاختبار المحجوزة (`@example.com`،
    و`@example.org`، و`@*.test`، و`@*.example`، و`@*.invalid`) تُرفض عند تسليم
    البريد ويعود الطلب بالرمز `500`. استبدل العنصر النائب `you@yourdomain.com`
    في الأمثلة بصندوق بريد وارد يمكنك قراءته فعلياً.

    - تعيد أخطاء التحقق من الصحة رمز الحالة HTTP `400` بإحدى صيغتين: `{"field":
    ["message", ...]}` للمشكلات على مستوى الحقول، أو `{"detail": "message"}`
    لأخطاء قواعد العمل. وترد قلة من أدوات التحقق من الصحة (قوة كلمة المرور عند
    التسجيل، وانتهاء صلاحية الرمز عند التحقق من البريد الإلكتروني) حالياً
    بمصفوفة مجردة `["message"]` بدلاً من الصيغة المحددة بمفتاح الحقل - وهو
    اختلاف معروف من جانب الخادم، لذا يجب أن يقبل كود العميل كلا الشكلين.

    - تعود أخطاء المصادقة على هيئة `{"detail": "..."}` مع HTTP `401` (رمز الحامل
    غير صالح) أو `403` (رمز الحامل مفقود / صلاحيات غير كافية).

    - تتضمن استجابات حد المعدل حقلاً باسم `wait` يحدد فترة الانتظار بالثواني.
servers:
  - url: https://apx.didit.me/auth/v2
    description: خادم مصادقة الإنتاج
security: []
tags:
  - name: Programmatic Auth
    description: >-
      دورة حياة الحساب بالبريد الإلكتروني وكلمة المرور: التسجيل، والتحقق، وتسجيل
      الدخول. يُرجع `access_token` الخاص بـ JWT الذي تستخدمه مع endpoints إدارة
      الحساب، بالإضافة إلى (عند التحقق) `client_id` و`api_key` لتطبيقك الأول.
  - name: Account Management
    description: >-
      الـ endpoints المُصادق عليها (JWT bearer) التي تعرض المؤسسات وتُنشئ
      التطبيقات أو تجلبها أو تُحدّثها. استخدم هذه الـ endpoints لاسترداد أو
      تدوير `api_key` الذي تستخدمه لمصادقة استدعاءات API للتحقق.
paths:
  /programmatic/login/:
    post:
      tags:
        - Programmatic Auth
      summary: تسجيل الدخول البرمجي
      description: >-
        مصادقة أي حساب Didit تم التحقق من بريده الإلكتروني وكلمة مروره وتلقي زوج
        JWT بتشفير RS256 (مدة الصلاحية الافتراضية 86400s). يمكن للحسابات المنشأة
        عبر البريد الإلكتروني/كلمة المرور في لوحة التحكم استخدام هذا الـ
        endpoint؛ ويجب على حسابات لوحة التحكم المعتمدة على OAuth فقط تعيين كلمة
        مرور أولاً.
      operationId: programmatic_login
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
            examples:
              Default:
                summary: تسجيل الدخول البرمجي
                value:
                  email: you@yourdomain.com
                  password: MyStr0ng!Pass
      responses:
        '200':
          description: >-
            تم تسجيل الدخول بنجاح. يُرجع زوج JWT جديداً. استخدم `access_token`
            كـ `Authorization: Bearer <token>` مقابل `/organizations/me/...`
            للبحث عن `org_id` و `app_id` و `api_key`. عندما يحتوي الحساب على
            تطبيق مصادقة أو مفتاح مرور، تتضمن الاستجابة `2fa_required: true` و
            `temp_token` بدلاً من الرموز المميزة.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
              examples:
                Success:
                  value:
                    access_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
                    refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
                    expires_in: 86400
                    message: Login successful
        '400':
          description: خطأ في التحقق. مشكلات على مستوى الحقول في نص الطلب.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
              examples:
                MissingFields:
                  summary: نص الطلب فارغ
                  value:
                    email:
                      - This field is required.
                    password:
                      - This field is required.
                InvalidEmail:
                  summary: بريد إلكتروني غير صالح
                  value:
                    email:
                      - Enter a valid email address.
        '401':
          description: تم رفض المصادقة.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                InvalidCredentials:
                  summary: >-
                    لم يتطابق البريد الإلكتروني مع كلمة المرور (يتم إرجاعه أيضاً
                    عندما يكون الحساب غير موجود، لتجنب تعداد المستخدمين)
                  value:
                    detail: Invalid email or password.
                NotVerified:
                  summary: الحساب موجود ولكن لم يتم التحقق من البريد الإلكتروني بعد
                  value:
                    detail: Please verify your email address before logging in.
                SSORequired:
                  summary: الحساب ينتمي إلى مؤسسة تتطلب SSO
                  value:
                    detail:
                      error: sso_required
                      message: Your organization 'Acme Corp' requires SSO login.
                      organization_name: Acme Corp
                      organization_slug: acme-corp
                      sso_url: /sso/acme-corp
        '403':
          description: >-
            تم استرداد الحساب ويجب إعداد طريقة تسجيل دخول جديدة قبل أن يتمكن من
            تسجيل الدخول. تم إرسال رابط للقيام بذلك عبر البريد الإلكتروني إلى
            عنوان الحساب. الحساب الذي تفرض مؤسسته SSO يحصل على `403` مع `error:
            sso_required` و `organization_name` و `organization_slug` و
            `sso_url`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecoverySetupRequiredError'
              examples:
                RecoverySetupRequired:
                  summary: حساب مسترد بدون طريقة تسجيل دخول حتى الآن
                  value:
                    recovery_setup_required: true
                    setup_link_sent: true
                    message: >-
                      You recovered your account. Open the link we emailed you
                      to set up a new sign-in method.
                    code: recovery_setup_required
        '429':
          description: >-
            الحساب مقفل (محاولات فاشلة حديثة كثيرة جداً على هذا البريد
            الإلكتروني) أو تم تطبيق حد المعدل على عنوان IP (محاولات كثيرة جداً
            من هذا العنوان). يتم إرجاعه أيضاً، مع رأس `Retry-After: 5`، عندما
            تقوم الخدمة مؤقتاً بالتحقق من أكبر عدد ممكن من كلمات المرور أو
            الرموز دفعة واحدة؛ أعد المحاولة بعد عدد الثواني المحدد.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
              examples:
                AccountLocked:
                  summary: تم تفعيل القفل التدريجي
                  value:
                    detail: >-
                      Account temporarily locked due to too many failed login
                      attempts. Please try again later.
                IPRateLimited:
                  summary: أكثر من 20/دقيقة أو 100/ساعة من عنوان IP هذا
                  value:
                    detail: >-
                      Too many login attempts from this IP address. Please wait
                      before trying again.
                PasswordChecksBusy:
                  summary: هناك عمليات فحص لكلمة المرور قيد التنفيذ أكثر من اللازم
                  value:
                    detail: >-
                      Too many sign-in attempts are being processed right now.
                      Please try again in a few seconds.
      security:
        - {}
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |-
            curl -X POST https://apx.didit.me/auth/v2/programmatic/login/ \
              -H "Content-Type: application/json" \
              -d '{
                "email": "you@yourdomain.com",
                "password": "MyStr0ng!Pass"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # This call needs no API key.
            client = Didit()

            result = client.account.login(
                email="you@yourdomain.com",
                password="MyStr0ng!Pass",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: |-
            import Didit from "@didit-protocol/sdk-node";

            // This call needs no API key.
            const didit = new Didit();

            const result = await didit.account.login({
              email: "you@yourdomain.com",
              password: "MyStr0ng!Pass",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// This call needs no API key.\nclient := didit.NewClient()\n\nresult, err := client.Account.Login(ctx, didit.LoginRequest{\n\tEmail:    \"you@yourdomain.com\",\n\tPassword: \"MyStr0ng!Pass\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: |-
            import me.didit.Didit;
            import me.didit.types.LoginRequest;

            // This call needs no API key.
            Didit client = new Didit();

            var result = client.account().login(LoginRequest.builder()
                    .email("you@yourdomain.com")
                    .password("MyStr0ng!Pass")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: |-
            <?php

            require 'vendor/autoload.php';

            use Didit\DiditClient;

            // This call needs no API key.
            $didit = new DiditClient();

            $result = $didit->account->login([
                'email' => 'you@yourdomain.com',
                'password' => 'MyStr0ng!Pass',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # This call needs no API key.
            didit = Didit::Client.new

            result = didit.account.login(
              email: "you@yourdomain.com",
              password: "MyStr0ng!Pass"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: |-
            using System;
            using System.Text.Json;
            using Didit;

            // This call needs no API key.
            using var client = new DiditClient();

            var result = await client.Account.LoginAsync(new LoginRequest
            {
                Email = "you@yourdomain.com",
                Password = "MyStr0ng!Pass",
            });
            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    LoginRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          format: email
          example: you@yourdomain.com
        password:
          type: string
          example: MyStr0ng!Pass
    LoginResponse:
      type: object
      properties:
        access_token:
          type: string
          description: >-
            JWT موقّع باستخدام RS256. يُستخدم كـ `Authorization: Bearer <token>`
            لنقاط endpoint لإدارة الحسابات.
        refresh_token:
          type: string
        expires_in:
          type: integer
          description: مدة صلاحية token الوصول بالثواني (الافتراضي 86400).
          example: 86400
        message:
          type: string
          example: Login successful
    ValidationError:
      description: >-
        جسم خطأ التحقق من الصحة. الغلاف المقصود هو خريطة `{field: ["message",
        ...]}` للأخطاء على مستوى الحقول أو غلاف بمفتاح فردي `{detail: "..."}`
        لأخطاء قواعد العمل. هناك عدد قليل من أدوات التحقق (قوة كلمة المرور عند
        التسجيل، وصلاحية الرمز عند verify-email) تستجيب حالياً بمصفوفة مجردة
        `["message"]` -- وهو تعارض معروف من جانب الخادم. يحتفظ المخطط أدناه بفرع
        المصفوفة المجردة حتى تتمكن التعليمات البرمجية للعميل المنشأة من هذه
        المواصفة من إلغاء تسلسل استجابات اليوم، ولكن يجب أن تعامل التعليمات
        البرمجية الجديدة للعميل هذه الاستجابة بالشكل المخصص للحقل المعني
        (`{password: [...]}` أو `{code: [...]}`) وسيتقارب عقد الخادم مع هذا
        الشكل.
      oneOf:
        - type: object
          additionalProperties:
            type: array
            items:
              type: string
          example:
            email:
              - Enter a valid email address.
        - type: object
          properties:
            detail:
              type: string
          example:
            detail: An account with this email already exists.
        - type: array
          items:
            type: string
          example:
            - Invalid or expired verification code.
    AuthError:
      type: object
      description: غلاف خطأ المصادقة / التفويض / غير موجود.
      properties:
        detail:
          type: string
          example: Invalid access token
    RecoverySetupRequiredError:
      type: object
      description: >-
        تم استرداد الحساب ولم يتم إعداد طريقة تسجيل دخول له بعد. لا يتم إصدار أي
        tokens؛ تم إرسال رابط لمرة واحدة لإعداد طريقة جديدة عبر البريد
        الإلكتروني إلى عنوان الحساب. افتحه وأعدّ إعداد الطريقة، ثم سجّل الدخول
        مجدداً.
      required:
        - recovery_setup_required
        - setup_link_sent
        - message
        - code
      properties:
        recovery_setup_required:
          type: boolean
          example: true
        setup_link_sent:
          type: boolean
          example: true
        message:
          type: string
          example: >-
            You recovered your account. Open the link we emailed you to set up a
            new sign-in method.
        code:
          type: string
          enum:
            - recovery_setup_required
          example: recovery_setup_required
    RateLimitError:
      type: object
      description: استجابة حد المعدل أو الحظر التدريجي. يمثل `wait` فترة التهدئة بالثواني.
      properties:
        detail:
          type: string
          example: >-
            Too many login attempts from this IP address. Please wait before
            trying again.

````

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