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

# اكتشاف الفواتير

> بدء عملية اكتشاف فواتير لحساب لدى أحد الشركاء

<div dir="ltr">
  ## نظرة عامة

  يسأل مُصدِر الفواتير عن المبالغ المستحقة حاليًا على حساب معيّن. الاستجابة هي `transactionId` تستعلم عنه دوريًا بعد ذلك؛ وعندما تبلغ المعاملة الحالة `READY`، تحتوي مصفوفة `bills[]` الخاصة بها على كل ما هو قابل للدفع.

  <Warning>
    **`200` إقرار بالاستلام، وليس نتيجة.** فهو يعني أن الطلب قُبِل وأن معاملة أُنشئت. الفواتير تصل لاحقًا، داخل المعاملة. لا تعتبر هذه الاستجابة أبدًا بمعنى «لا يترتب على الحساب أي مبلغ».
  </Warning>

  الاكتشاف لا يحرّك أي أموال ولا يُلزمك بشيء. من الآمن تشغيله قبل أن تعرض على العميل ما هو مستحق عليه.

  ## متن الطلب

  <ParamField body="partner" type="string" required>
    مُصدِر الفواتير المطلوب الاستعلام عنه. قيمة واحدة بالضبط من `ADE`، `SONELGAZ`، `SEAAL`، `AADL`، `Algérie Télécom` — مع الحفاظ على العلامات (accents) كما هي.

    راجع [قائمة الشركاء](/ar/api-reference/bill-payment/list-partners) أولًا؛ الشريك الذي حالته `UNAVAILABLE` يُجيب بـ `503 PARTNER_UNAVAILABLE`.
  </ParamField>

  <ParamField body="account" type="object" required>
    الحساب المطلوب البحث عنه. يجب أن يحمل **معرّفًا واحدًا بالضبط** — راجع [معرّفات الحساب](#account-identifiers) أدناه. عدم إرسال أي معرّف، أو إرسال معرّفين، مرفوض.
  </ParamField>

  <ParamField body="ref" type="string" required>
    مرجعك الخاص لعملية الاكتشاف هذه. 100 حرف كحد أقصى، وفريد بين معاملاتك النشطة لدى هذا الشريك.

    إعادة استخدام `ref` تُجيب بـ `403 DUPLICATED_REF`. وهو أيضًا الطريقة التي تستعيد بها استجابة ضائعة — راجع [الحصول على المعاملة بالمرجع](/ar/api-reference/bill-payment/check-by-ref).
  </ParamField>

  ## معرّفات الحساب

  أرسل الحقل الذي يخص الشريك الذي تستعلم عنه. وهو أيضًا الحقل الذي تُرجعه واجهة API في `account` في كل معاملة لهذا الشريك.

  | الشريك            | الحقل            | ملاحظات                                                                    |
  | ----------------- | ---------------- | -------------------------------------------------------------------------- |
  | `ADE`             | `reference`      | مرجع العميل، حتى 50 حرفًا                                                  |
  | `SEAAL`           | `reference`      | مرجع العميل، حتى 50 حرفًا                                                  |
  | `SONELGAZ`        | `contractNumber` | رقم العقد، حتى 50 حرفًا                                                    |
  | `AADL`            | `aadlNumber`     | رقم الملف السكني، حتى 50 حرفًا                                             |
  | `Algérie Télécom` | `phoneNumber`    | خط هاتف ثابت جزائري، `0` أو `+213` متبوعًا برقم من 2 إلى 4 ثم 7 أرقام أخرى |

  تُقبَل أيضًا صيغتان أكثر تفصيلًا حين يحتاج مُصدِر الفواتير إلى أكثر من رقم واحد لتحديد الفاتورة:

  <AccordionGroup>
    <Accordion title="sonelgaz — صيغة الفاتورة">
      الحقول الثلاثة كلها مطلوبة معًا.

      ```json theme={null}
      {
        "partner": "SONELGAZ",
        "account": {
          "sonelgaz": {
            "invoice_number": "9876543210",
            "amount_without_stamp": "15000",
            "ebb_key": "ABC123"
          }
        },
        "ref": "disc-inv-2026-0042"
      }
      ```

      `invoice_number` حتى 20 حرفًا، و`amount_without_stamp` حتى 20، و`ebb_key` حتى 30.
    </Accordion>

    <Accordion title="ade — صيغة الفاتورة">
      الحقول الأربعة كلها مطلوبة معًا.

      ```json theme={null}
      {
        "partner": "ADE",
        "account": {
          "ade": {
            "sub_id": "000123456789",
            "period": "07/2026",
            "amount": "12000",
            "pay_key": "1234567"
          }
        },
        "ref": "disc-inv-2026-0043"
      }
      ```

      `sub_id` من 12 حرفًا بالضبط، و`period` بتنسيق `MM/YYYY`، و`amount` حتى 20 حرفًا، و`pay_key` من 7 أحرف بالضبط.
    </Accordion>

    <Accordion title="electronic_payment_key — مفتاح من 25 حرفًا">
      مقبول لدى ADE وSEAAL كبديل عن `reference`. يجب أن يكون **من 25 حرفًا بالضبط**.

      ```json theme={null}
      {
        "partner": "ADE",
        "account": { "electronic_payment_key": "0123456789012345678901234" },
        "ref": "disc-inv-2026-0044"
      }
      ```
    </Accordion>
  </AccordionGroup>

  <Warning>
    **معرّف واحد بالضبط.** تُحسب `reference` و`contractNumber` و`aadlNumber` و`electronic_payment_key` ضمن الخانة نفسها، وكذلك `phoneNumber` و`phone_number`؛ أما `sonelgaz` و`ade` فلكل منهما خانته الخاصة. عدم إرسال أي منها، أو إرسال اثنين، مرفوض بـ `400`.
  </Warning>

  ## الاستجابة

  <ResponseField name="success" type="boolean" required>
    `true` عندما يُقبَل الاكتشاف.
  </ResponseField>

  <ResponseField name="data" type="object" required>
    <Expandable title="properties">
      <ResponseField name="transactionId" type="string" required>
        المعاملة المطلوب الاستعلام عنها دوريًا. سلسلة سداسية عشرية من 24 حرفًا بأحرف صغيرة.
      </ResponseField>

      <ResponseField name="ref" type="string" required>
        قيمة `ref` التي أرسلتها، مُعادة إليك.
      </ResponseField>

      <ResponseField name="status" type="string" required>
        دائمًا `PENDING` عند هذه النقطة.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="meta" type="object" required>
    <Expandable title="properties">
      <ResponseField name="timestamp" type="string" required>
        وقت الاستجابة، ISO 8601 بتوقيت UTC.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="requestId" type="string" required>
    معرّف الربط، يُرسل أيضًا في ترويسة الاستجابة `X-Request-Id`.
  </ResponseField>

  ## الأمثلة

  <CodeGroup>
    ```bash cURL theme={null}
    curl https://billapi.oneclickdz.com/v3/bills/discover \
      -X POST \
      -H "Content-Type: application/json" \
      -H "X-Access-Token: YOUR_API_KEY" \
      -d '{
        "partner": "ADE",
        "account": { "reference": "0123456789012345678901234" },
        "ref": "disc-inv-2026-0042"
      }'
    ```

    ```javascript Node.js theme={null}
    const response = await fetch(
      "https://billapi.oneclickdz.com/v3/bills/discover",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Access-Token": process.env.ONECLICKDZ_API_KEY,
        },
        body: JSON.stringify({
          partner: "ADE",
          account: { reference: "0123456789012345678901234" },
          ref: "disc-inv-2026-0042",
        }),
      },
    );

    const body = await response.json();

    if (!body.success) {
      throw new Error(`${body.error.code}: ${body.error.message}`);
    }

    // Accepted — the bills are not here yet. Poll this id until READY.
    console.log(body.data.transactionId);
    ```

    ```python Python theme={null}
    import os
    import requests

    response = requests.post(
        'https://billapi.oneclickdz.com/v3/bills/discover',
        headers={
            'Content-Type': 'application/json',
            'X-Access-Token': os.getenv('ONECLICKDZ_API_KEY')
        },
        json={
            'partner': 'ADE',
            'account': {'reference': '0123456789012345678901234'},
            'ref': 'disc-inv-2026-0042'
        }
    )

    body = response.json()

    if not body['success']:
        raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")

    # Accepted — the bills are not here yet. Poll this id until READY.
    print(body['data']['transactionId'])
    ```

    ```php PHP theme={null}
    <?php
    $payload = [
        'partner' => 'ADE',
        'account' => ['reference' => '0123456789012345678901234'],
        'ref'     => 'disc-inv-2026-0042'
    ];

    $ch = curl_init('https://billapi.oneclickdz.com/v3/bills/discover');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

    $body = json_decode(curl_exec($ch), true);
    curl_close($ch);

    if (!$body['success']) {
        throw new Exception($body['error']['code'] . ': ' . $body['error']['message']);
    }

    // Accepted — the bills are not here yet. Poll this id until READY.
    echo $body['data']['transactionId'];
    ?>
    ```
  </CodeGroup>

  ### استجابة النجاح

  ```json theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "68b2f4c1a7d3e9f204c81a55",
      "ref": "disc-inv-2026-0042",
      "status": "PENDING"
    },
    "meta": {
      "timestamp": "2026-08-31T10:15:32.194Z"
    },
    "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
  }
  ```

  استعلم دوريًا عن [الحصول على المعاملة بالمعرّف](/ar/api-reference/bill-payment/check-by-id) حتى تصبح `status` هي `READY`، ثم اقرأ `bills[]`:

  ```json theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "68b2f4c1a7d3e9f204c81a55",
      "ref": "disc-inv-2026-0042",
      "type": "discovery",
      "status": "READY",
      "partner": "ADE",
      "account": { "reference": "0123456789012345678901234" },
      "bills": [
        {
          "billId": "sbx_bill_68b2f4c1a7d3e9f204c81a55_0",
          "amount": 443.39,
          "fee": 30.00,
          "label": "Facture ADE"
        }
      ],
      "currency": "DZD",
      "createdAt": "2026-08-31T10:15:32.194Z",
      "updatedAt": "2026-08-31T10:15:33.008Z",
      "completedAt": "2026-08-31T10:15:33.008Z"
    },
    "meta": {
      "timestamp": "2026-08-31T10:15:34.120Z"
    },
    "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
  }
  ```

  ## استجابات الخطأ

  <AccordionGroup>
    <Accordion title="400 — خطأ في التحقق">
      **متن الطلب لم يطابق المخطط.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "ERR_VALIDATION",
          "message": "ref is required",
          "details": ["ref is required"]
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      يسرد `details` كل حقل فشل، وليس الأول فقط. الأسباب الشائعة: غياب `ref`، أو `partner` ليست إحدى القيم الخمس، أو `account` بلا معرّف أو بمعرّفين، أو `electronic_payment_key` ليس من 25 حرفًا بالضبط، أو `phoneNumber` ليس خط هاتف ثابت جزائري صالح.

      **ما العمل:** صحّح الطلب. إعادة إرساله دون تغيير تُرجع الخطأ نفسه.
    </Accordion>

    <Accordion title="400 — حساب غير صالح">
      **المعرّف مقبول من حيث البنية لكنه غير قابل للاستخدام مع هذا الشريك.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "INVALID_ACCOUNT",
          "message": "The provided account identifier is invalid."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** اطلب من العميل التحقق من الرقم المدوّن على فاتورته. هذا هو الخطأ الذي تعرضه له؛ أما `ERR_VALIDATION` فهو لسجلاتك.
    </Accordion>

    <Accordion title="401 — رمز وصول مفقود أو غير صالح">
      **المفتاح غائب أو مرفوض.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "INVALID_ACCESS_TOKEN",
          "message": "The provided access token is invalid."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      غياب الترويسة يُرجع `MISSING_ACCESS_TOKEN` بدلًا من ذلك، بنفس حالة HTTP.

      **ما العمل:** تحقق من المفتاح عبر [التحقق من مفتاح API](/ar/api-reference/bill-payment/validate-key).
    </Accordion>

    <Accordion title="403 — مرجع مكرر">
      **سبق أن استخدمت هذا `ref` مع هذا الشريك.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "DUPLICATED_REF",
          "message": "A transaction with this ref already exists for this partner."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** **لا** تعد المحاولة بمرجع `ref` جديد بشكل أعمى — فستبدأ عملية اكتشاف ثانية للحساب نفسه. ابحث عن العملية الموجودة عبر [الحصول على المعاملة بالمرجع](/ar/api-reference/bill-payment/check-by-ref) وتابع من حالتها.
    </Accordion>

    <Accordion title="409 — الفاتورة مدفوعة مسبقًا">
      **هذا الحساب سُدِّد مؤخرًا بالفعل، لذا رُفض اكتشاف جديد.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "BILL_ALREADY_PAID",
          "message": "This bill has already been paid."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** هذا حارس ضد الدفع المزدوج، وليس فشلًا. ابحث عن المعاملة الناجحة في [قائمة المعاملات](/ar/api-reference/bill-payment/list-transactions) واعرض على العميل ذلك الإيصال.
    </Accordion>

    <Accordion title="409 — دفعة قيد التنفيذ">
      **دفعة أخرى لهذا الحساب لم تنتهِ بعد.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "PAYMENT_IN_PROGRESS",
          "message": "A payment for this account is currently in progress."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** انتظر حتى تبلغ تلك الدفعة حالة نهائية، ثم ابدأ من جديد. لا تُشغّل الاثنتين بالتوازي.
    </Accordion>

    <Accordion title="503 — الشريك غير متاح">
      **تعذّر الوصول إلى مُصدِر الفواتير، أو أنه موقوف حاليًا.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "PARTNER_UNAVAILABLE",
          "message": "Partner temporarily unavailable — please try again later."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** حدّث [قائمة الشركاء](/ar/api-reference/bill-payment/list-partners) وأعد المحاولة لاحقًا. لم تُنشأ أي معاملة ولم يُخصم أي مبلغ. هذه الاستجابة لا تحمل `Retry-After`؛ طبّق التراجع التدريجي من جانبك.
    </Accordion>

    <Accordion title="503 — المصادقة غير متاحة">
      **لم نتمكن من التحقق من مفتاحك في الوقت المحدد. مفتاحك ليس هو المشكلة.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "AUTH_UNAVAILABLE",
          "message": "Authentication is temporarily unavailable. Please retry shortly."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** انتظر مدة `Retry-After` (5 ثوانٍ) وأعد إرسال الطلب نفسه بالمرجع `ref` نفسه.
    </Accordion>

    <Accordion title="503 — الخدمة غير متاحة">
      **واجهة Bill Payment API في صيانة مُخطط لها.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "SERVICE_UNAVAILABLE",
          "message": "The service is temporarily unavailable. Please retry shortly."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** التزم بـ `Retry-After` وأعد المحاولة بالمرجع `ref` نفسه.
    </Accordion>

    <Accordion title="500 — خطأ داخلي">
      **حدث خلل من جانبنا.**

      ```json theme={null}
      {
        "success": false,
        "error": {
          "code": "INTERNAL_ERROR",
          "message": "An unexpected error occurred."
        },
        "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
      }
      ```

      **ما العمل:** تحقق مما إذا كان الاكتشاف قد أُنشئ عبر [الحصول على المعاملة بالمرجع](/ar/api-reference/bill-payment/check-by-ref) قبل إعادة المحاولة، وأرسل `requestId` إلى الدعم إذا استمرت المشكلة.
    </Accordion>
  </AccordionGroup>

  ## حدّ الـ 200 دينار جزائري في الاكتشاف

  تُستبعَد الفواتير التي تقل عن **200 دينار جزائري** أثناء الاكتشاف ولا تظهر أبدًا في `bills[]`.

  لذلك فإن معاملة بحالة `READY` مع `bills[]` فارغة تعني أحد أمرين، وواجهة API لا تفرّق بينهما:

  * لا يترتب على الحساب أي مبلغ، أو
  * كل ما يترتب عليه يقل عن حدّ الـ 200 دينار جزائري.

  <Note>
    صُغ هذا بعناية لعملائك. عبارة «لا توجد فواتير قابلة للدفع حاليًا» دقيقة؛ أما «لا يترتب عليك أي مبلغ» فليست كذلك.
  </Note>

  ## منع الطلبات المكررة

  يجعل `ref` عملية الاكتشاف آمنة لإعادة المحاولة. إذا حجب خطأ في الشبكة الاستجابة، فابحث عن `ref` بدلًا من إرسال اكتشاف ثانٍ.

  ```javascript theme={null}
  async function discoverSafely(partner, account, ref) {
    try {
      const response = await fetch(
        "https://billapi.oneclickdz.com/v3/bills/discover",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-Access-Token": process.env.ONECLICKDZ_API_KEY,
          },
          body: JSON.stringify({ partner, account, ref }),
        },
      );

      const body = await response.json();

      if (body.success) {
        return body.data.transactionId;
      }

      // Already started earlier — recover it instead of starting a second one.
      if (body.error.code === "DUPLICATED_REF") {
        return await findByRef(ref, partner);
      }

      throw new Error(`${body.error.code}: ${body.error.message}`);
    } catch (networkError) {
      // The request may still have been accepted. Check before retrying.
      const existing = await findByRef(ref, partner).catch(() => null);
      if (existing) return existing;
      throw networkError;
    }
  }

  async function findByRef(ref, partner) {
    const url = new URL(
      "https://billapi.oneclickdz.com/v3/bills/transactions/by-ref",
    );
    url.searchParams.set("ref", ref);
    url.searchParams.set("partner", partner);

    const response = await fetch(url, {
      headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
    });

    const body = await response.json();
    if (!body.success) throw new Error(body.error.code);
    return body.data.transactionId;
  }
  ```

  المرجع `ref` الجيد مُشتق من شيء تخزّنه أصلًا — معرّف فاتورتك أو طلبك — حتى تتمكن دائمًا من إعادة بنائه. راجع [اكتشاف الفواتير](/ar/bill-payment-guides/2-discovering-bills) للاطلاع على طريقة للتسمية.

  ## دورة حياة الحالة

  <Steps>
    <Step title="PENDING">
      الاستجابة التي تلقيتها للتو. الاكتشاف في قائمة الانتظار وقيد التنفيذ.
    </Step>

    <Step title="READY">
      انتهى الاكتشاف. `bills[]` موجودة — وقد تكون فارغة. اختر `billId` واستدعِ [دفع فاتورة](/ar/api-reference/bill-payment/pay-bill).
    </Step>

    <Step title="FAILED">
      لم يتمكن الاكتشاف من الاكتمال. يوضّح `error.code` السبب: `INVALID_ACCOUNT` أو `PARTNER_UNAVAILABLE` أو `BILL_ALREADY_PAID` أو `PAYMENT_DECLINED`.
    </Step>
  </Steps>

  [مرجع الحالات الكامل →](/ar/api-reference/bill-payment/check-by-id#status-lifecycle)

  ## أفضل الممارسات

  <CardGroup cols={2}>
    <Card title="تحقق من الشريك أولًا" icon="building-columns">
      خريطة شركاء مخزّنة مؤقتًا تتيح لك إخفاء مُصدِر فواتير غير متاح قبل أن يُدخل العميل رقم حسابه.
    </Card>

    <Card title="اشتقّ المرجع، لا تخترعه" icon="fingerprint">
      ابنِ `ref` من معرّف طلبك الخاص حتى تتمكن دائمًا من البحث عن المعاملة مجددًا.
    </Card>

    <Card title="لا تفترض أبدًا أن 200 تعني فارغًا" icon="triangle-exclamation">
      الفواتير تصل في المعاملة، لا في هذه الاستجابة. استعلم دوريًا قبل أن تخبر العميل بأي شيء.
    </Card>

    <Card title="اقرأ fee من الاستجابة" icon="calculator">
      كل فاتورة تحمل `fee` الخاص بها. لا تُعِد حسابه في كودك.
    </Card>
  </CardGroup>

  ## Endpoints ذات الصلة

  <CardGroup cols={3}>
    <Card title="قائمة الشركاء" icon="building-columns" href="/ar/api-reference/bill-payment/list-partners">
      تحقق من التوفر أولًا
    </Card>

    <Card title="الحصول على المعاملة بالمعرّف" icon="id-card" href="/ar/api-reference/bill-payment/check-by-id">
      استعلم دوريًا عن الفواتير
    </Card>

    <Card title="دفع فاتورة" icon="money-bill-transfer" href="/ar/api-reference/bill-payment/pay-bill">
      ادفع إحداها
    </Card>

    <Card title="الحصول على المعاملة بالمرجع" icon="tag" href="/ar/api-reference/bill-payment/check-by-ref">
      استعد استجابة ضائعة
    </Card>

    <Card title="اكتشاف الفواتير" icon="magnifying-glass" href="/ar/bill-payment-guides/2-discovering-bills">
      الشرح الكامل
    </Card>

    <Card title="الشركاء والحسابات" icon="address-card" href="/ar/bill-payment-guides/1-partners-and-accounts">
      قواعد المعرّفات لكل شريك
    </Card>
  </CardGroup>
</div>
