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

# Vito API والمشتريات

> دع التطبيقات المعتمَدة تخصم من Vito الخاص بك مع تأكيد PIN، وأدر طلبات الدفع من صفحة المشتريات.

<Info>
  يتطلّب عضوية **سيلفر** أو أعلى — للتقديم ولكل استدعاء موثَّق. إن انقضت عضوية مالك المفتاح، يُجمَّد المشروع حتى يُجدِّد اشتراكه.
</Info>

واجهة REST تتيح لتطبيقك التعامل مع رصيد [Vito](/ar/members/vito) الخاص بالمستخدم من داخل ديسكورد — قراءته، أو الخصم منه، أو الإضافة إليه، أو تحريكه بين المستخدمين. كل نقاط النهاية تُعيد JSON وتقع تحت الإصدار `/v1`.

<Warning>
  **Vito لا ينتقل من أو إلى أموال حقيقية أبداً.** هو يتحرّك بين أرصدة فيتوكس فقط.
</Warning>

## الحصول على الوصول

الوصول يُمنَح **لكل مشروع على حدة**. تحتاج الأربعة جميعاً:

<Steps>
  <Step title="عضوية نشطة، سيلفر أو أعلى">
    تُفحَص عند كل استدعاء، لا عند الموافقة فقط.
  </Step>

  <Step title="طلب مطوّر تمت الموافقة عليه">
    يُقدَّم من صفحة Vito API في لوحة التحكم، ويراجعه فريق فيتوكس يدوياً.
  </Step>

  <Step title="الموافقة على شروط مطوّري API">
    تُقَرّ عند تقديم الطلب.
  </Step>

  <Step title="النطاقات التي يحتاجها مشروعك">
    يمنحها طاقم فيتوكس بناءً على ما وصفته.
  </Step>
</Steps>

<Tip>
  كن محدَّداً في وصف ما تبنيه وكيف ستخزّن المفتاح. الطلبات المبهمة هي التي تُرفَض.
</Tip>

### النطاقات

| النطاق              | يمنح                                     |
| ------------------- | ---------------------------------------- |
| `balance:read`      | قراءة رصيد Vito الخاص بمستخدم            |
| `deduct:create`     | الخصم من رصيد مستخدم                     |
| `credit:create`     | إضافة Vito لمستخدم، مموَّلة من رصيدك أنت |
| `transfer:create`   | تحريك Vito بين مستخدمَين                 |
| `transactions:read` | عرض وقراءة معاملات مشروعك                |

## المصادقة

أرسل مفتاحك السرّي كرمز Bearer:

```bash theme={null}
Authorization: Bearer vito_live_xxxxxxxxxxxxxxxx
```

طبقتان اختياريتان تزيدان تحصين المشروع:

* **قائمة عناوين IP المسموح بها** — حصر الاستدعاءات بعناوين خوادم بعينها
* **حدود المعدّل** — سقوف لكل مشروع تتوسّع مع مستوى عضوية المالك

### المفاتيح: التدوير والتخزين

<Warning>
  **يُكشَف المفتاح وسرّ التوقيع مرة واحدة فقط.** بعد الموافقة لديك **نافذة 7 أيام** لكشفهما من تبويب مفاتيح API. لا يحتفظ فيتوكس إلا بتجزئة ولا يمكنه عرضهما مجدداً — إن فاتتك النافذة فعليك التدوير للحصول على مفتاح جديد.
</Warning>

* احتفظ به **على الخادم فقط** — من يملكه يستطيع الخصم من مستخدميك
* دوّره من تبويب مفاتيح API. يظل المفتاح السابق يعمل **24 ساعة** كفترة سماح كي تنشر التحديث دون انقطاع
* سرّ توقيع الـ webhook يُدوَّر بشكل منفصل، وله فترة تداخل 24 ساعة خاصة به
* إن تسرّب المفتاح، دوّره فوراً

## الخصم من مستخدم

<Warning>
  **مفتاحك وحده لا يستطيع تحريك Vito الخاص بمستخدم.** كل عملية خصم تتطلّب موافقة المستخدم برمز PIN الخاص بمحفظته، على `vetox.io` — لا داخل تطبيقك ولا داخل ديسكورد.
</Warning>

<Steps>
  <Step title="تطبيقك يستدعي POST /v1/deduct">
    مع المستخدم، والمبلغ، و`guildId` الذي انطلقت منه العملية، وتفاصيل المنتج.
  </Step>

  <Step title="Vito يُعيد confirmUrl">
    طلب تأكيد معلّق، صالح **10 دقائق**. تُرسَل للمستخدم رسالة خاصة أيضاً.
  </Step>

  <Step title="المستخدم يوافق برمز PIN">
    على `vetox.io`.
  </Step>

  <Step title="Vito يسوّي العملية ويُخطِر">
    يُخصَم الرصيد، وتُسجَّل المعاملة، ويُرسَل webhook موقَّع إن كنت قد ضبطت واحداً.
  </Step>

  <Step title="تطبيقك يتحقّق ويُكمِل">
    تحقّق من التوقيع، ثم افتح المحتوى أو سلّم المنتج.
  </Step>
</Steps>

<Warning>
  **أكمِل عمليتك عند `confirmation.completed` فقط** — لا عند رد `/deduct`. الخصم لا يكون نهائياً عند تلك النقطة.
</Warning>

### مُعامِلات الطلب — `/v1/deduct`

| الحقل         | مطلوب   | ملاحظات                                                                             |
| ------------- | ------- | ----------------------------------------------------------------------------------- |
| `discordId`   | **نعم** | معرّف ديسكورد للمستخدم — رقم snowflake من 17 إلى 20 خانة                            |
| `amount`      | **نعم** | عدد صحيح موجب                                                                       |
| `guildId`     | **نعم** | سيرفر ديسكورد الذي انطلقت منه العملية. كل عملية خصم يجب أن تأتي من سيرفر            |
| `reason`      | لا      | حتى 256 حرفاً. يُعرَض للمستخدم ويُعاد في الـ webhook                                |
| `merchantRef` | لا      | مرجعك الخاص، حتى 128 حرفاً. استخدمه لمطابقة الـ webhook بسجلاتك                     |
| `product`     | لا      | `{ type, name, description?, imageUrl? }` — يظهر في صفحة التأكيد وفي الرسالة الخاصة |
| `imageUrl`    | لا      | يجب أن يبدأ بـ `https://`                                                           |
| `metadata`    | لا      | حتى **10** أزواج نصية (مفتاح/قيمة)، تُمرَّر كما هي                                  |

## إضافة رصيد لمستخدم

`POST /v1/add` يضيف Vito لمستخدم **من رصيدك أنت** — للمكافآت أو الاستردادات. نفس حقول `/deduct` عدا `guildId` و`product`.

<Note>
  على عكس الخصم، الإضافة **بلا خطوة تأكيد** — تُسوّى فوراً. تتطلّب النطاق `credit:create` ورصيداً كافياً، وإلا أعاد الاستدعاء **402 `VITO_INSUFFICIENT_OWNER_FUNDS`**.
</Note>

## الرسوم

كل عملية خصم تُسوّى لصالحك بعد خصم رسوم المنصّة — بنفس جدول تحويلات Vito داخل التطبيق، وبحسب مستوى عضويتك **أنت**:

| عضويتك              | الرسوم |
| ------------------- | ------ |
| نورمال، سيلفر، جولد | 7%     |
| بلاتينيوم           | 6%     |
| دايموند             | 5%     |

<Note>
  المبالغ **5 Vito أو أقل بلا رسوم**، والإضافات عبر `/v1/add` بلا رسوم دائماً.
</Note>

## Webhooks

أضف رابط استدعاء واحداً أو أكثر بصيغة `https` من تبويب الإعدادات. يرسل Vito طلب `POST` موقَّعاً كلما وصل طلب تأكيد إلى حالة نهائية.

<Warning>
  لا تُرسَل الـ webhooks إلا إذا كان لمشروعك **رابط استدعاء وسرّ توقيع معاً**. اكشف السرّ (`whsec_…`) مرة واحدة من تبويب مفاتيح API.
</Warning>

### التحقّق من التوقيع

كل عملية تسليم تحمل ترويسة `X-Vito-Signature`:

```text theme={null}
X-Vito-Signature: ts=<unix>;h1=<hex>
```

وترافقها ترويستان إضافيتان — استخدم `X-Vito-Event-Id` مفتاحاً لمنع التكرار، فإعادة المحاولة تُرسل المعرّف نفسه:

| الترويسة            | تحتوي                                                 |
| ------------------- | ----------------------------------------------------- |
| `X-Vito-Event-Id`   | معرّف ثابت لهذا الحدث — لا يتغيّر عبر إعادات المحاولة |
| `X-Vito-Event-Type` | مثل `confirmation.completed`                          |

<Warning>
  **أثناء تدوير سرّ التوقيع تحمل الترويسة أكثر من توقيع واحد**، الأحدث أولاً:

  ```text theme={null}
  X-Vito-Signature: ts=<unix>;h1=<new>;h1=<old>
  ```

  اقبل التسليم إذا طابق **أي** `h1`. المُتحقِّق الذي يقرأ الأول فقط سيرفض كل webhook إلى أن ينشر السرّ الجديد — وهو ما يُبطل الغرض من فترة التداخل البالغة 24 ساعة.
</Warning>

أعِد حساب HMAC على `<ts>:<rawBody>` بسرّ التوقيع الخاص بك، وقارِن بزمن ثابت.

```js theme={null}
const crypto = require('crypto');

function verify(rawBody, header, secret) {
  const parts = header.split(';');
  const ts = parts.find(p => p.startsWith('ts='))?.slice(3);
  const sigs = parts.filter(p => p.startsWith('h1=')).map(p => p.slice(3));
  if (!ts || sigs.length === 0) return false;

  // Reject anything older than ~5 minutes — replay protection.
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const expected = Buffer.from(
    crypto.createHmac('sha256', secret).update(`${ts}:${rawBody}`).digest('hex'),
  );

  // Any matching signature is valid — a rotation emits several.
  return sigs.some(sig => {
    const actual = Buffer.from(sig);
    // timingSafeEqual throws when the lengths differ, so check first.
    return (
      actual.length === expected.length && crypto.timingSafeEqual(actual, expected)
    );
  });
}
```

<Warning>
  تحقّق من **الجسم الخام** للطلب، قبل أي تحليل JSON أو وسيط يعيد صياغته.
</Warning>

### الأحداث

خمسة أنواع من الأحداث، تشترك كلها في شكل حمولة واحد. الحقل `data.status` يحمل النتيجة.

| الحدث                    | المعنى                                                                   |
| ------------------------ | ------------------------------------------------------------------------ |
| `confirmation.completed` | تمت الموافقة والخصم. يحمل `transactionId`. **أكمِل عمليتك هنا**          |
| `confirmation.failed`    | تعذّر الإكمال — رصيد غير كافٍ أو خطأ داخلي. يحمل `failureReason`         |
| `confirmation.expired`   | لم يُؤكَّد خلال 10 دقائق. لم يتحرّك أي Vito                              |
| `confirmation.cancelled` | ألغاه المستخدم. لم يتحرّك أي Vito                                        |
| `credit.completed`       | تمّت تسوية إضافة `/add` مموَّلة من المالك. يُرسَل فوراً — بلا خطوة تأكيد |

<Note>
  تُعاد محاولة الـ webhooks **5 مرات مع تباعد تصاعدي**. ردّ بـ 2xx بسرعة ونفّذ التسليم لديك بشكل غير متزامن.
</Note>

## رموز الأخطاء

كل رد مُغلَّف. النجاح يحمل `data`، والفشل يحمل `error`، ولا يجتمعان أبداً:

```json theme={null}
{
  "success": false,
  "error": {
    "type": "Forbidden",
    "message": "API key lacks the required scope for this operation.",
    "code": "VITO_INSUFFICIENT_SCOPE"
  },
  "requestId": "…",
  "timestamp": 1735161600000
}
```

<Warning>
  **كل رمز مسبوق بـ `VITO_`.** اعتمد على النص الكامل في شروطك — لن يظهر `RATE_LIMITED` أو `FORBIDDEN` مجرّداً في أي رد.
</Warning>

| الرمز                                 | الحالة | المعنى                                                        |
| ------------------------------------- | ------ | ------------------------------------------------------------- |
| `VITO_VALIDATION_ERROR`               | 400    | حقل ناقص أو بصيغة غير صحيحة                                   |
| `VITO_INVALID_AMOUNT`                 | 400    | `amount` ليس عدداً صحيحاً موجباً                              |
| `VITO_AMOUNT_LIMIT_EXCEEDED`          | 400    | تجاوز سقف المعاملة الواحدة لديك                               |
| `VITO_DAILY_VOLUME_EXCEEDED`          | 400    | هذا الاستدعاء سيتجاوز سقف حجمك اليومي                         |
| `VITO_SELF_TRANSFER`                  | 400    | المُرسِل والمستلِم هما المستخدم نفسه                          |
| `VITO_INVALID_API_KEY`                | 401    | مفتاح ناقص أو غير صالح أو ملغى أو غير معروف                   |
| `VITO_INSUFFICIENT_FUNDS`             | 402    | رصيد المستخدم لا يغطّي المبلغ                                 |
| `VITO_INSUFFICIENT_OWNER_FUNDS`       | 402    | رصيدك **أنت** لا يكفي لتمويل `/add`                           |
| `VITO_INSUFFICIENT_SCOPE`             | 403    | المفتاح لا يملك النطاق الذي تتطلّبه نقطة النهاية              |
| `VITO_IP_NOT_ALLOWED`                 | 403    | عنوان IP المُستدعي ليس في قائمة السماح                        |
| `VITO_OWNER_MEMBERSHIP_INACTIVE`      | 403    | انقضت عضوية المالك — مجمّد حتى يُجدِّد                        |
| `VITO_GUILD_NOT_ALLOWED`              | 403    | `guildId` ليس ضمن قائمة السيرفرات المسموح بها للمشروع         |
| `VITO_TOS_NOT_ACCEPTED`               | 403    | شروط المطوّرين غير مقبولة، أو هناك نسخة أحدث بانتظار الموافقة |
| `VITO_PROJECT_FROZEN`                 | 403    | مجمَّد — غالباً بسبب انقضاء عضوية المالك                      |
| `VITO_PROJECT_SUSPENDED`              | 403    | موقوف من طاقم فيتوكس                                          |
| `VITO_PROJECT_BANNED`                 | 403    | محظور من طاقم فيتوكس                                          |
| `VITO_USER_BLACKLISTED`               | 403    | المستخدم محظور من عمليات Vito                                 |
| `VITO_ACCOUNT_LOCKED`                 | 403    | محفظة المستخدم مقفلة بعد محاولات PIN فاشلة                    |
| `VITO_USER_NOT_FOUND`                 | 404    | لا يوجد حساب Vito لمعرّف ديسكورد هذا                          |
| `VITO_CONFIRMATION_NOT_FOUND`         | 404    | رمز تأكيد غير معروف                                           |
| `VITO_IDEMPOTENCY_CONFLICT`           | 409    | نفس `Idempotency-Key` بجسم طلب مختلف                          |
| `VITO_IDEMPOTENCY_IN_PROGRESS`        | 409    | طلب مطابق ما زال قيد التنفيذ — أعد المحاولة بعد قليل          |
| `VITO_CONFIRMATION_ALREADY_PROCESSED` | 409    | طلب التأكيد وصل حالة نهائية من قبل                            |
| `VITO_KEY_ROTATION_IN_PROGRESS`       | 409    | هناك تدوير جارٍ بالفعل                                        |
| `VITO_CONFIRMATION_EXPIRED`           | 410    | انقضت نافذة التأكيد البالغة 10 دقائق                          |
| `VITO_RATE_LIMITED`                   | 429    | تمهّل وأعد المحاولة                                           |
| `VITO_INTERNAL_ERROR`                 | 500    | عطل غير متوقّع لدينا                                          |

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

| عضوية المالك         | لكل دقيقة | لكل ساعة |
| -------------------- | --------- | -------- |
| بلا                  | 60        | 1,000    |
| سيلفر أو جولد        | 180       | 5,000    |
| بلاتينيوم أو دايموند | 600       | 15,000   |

يوجد أيضاً حد لكل عنوان IP يساوي نصف حصّتك في الدقيقة، بحد أدنى 30.

<Warning>
  تحت الحمل الكثيف **تفشل نقاط نهاية الكتابة بشكل مغلق** — يُرفَض الخصم بدل المخاطرة بإنفاق مزدوج، بينما تفشل نقاط نهاية القراءة بشكل مفتوح. عامِل الكتابة المرفوضة على أنها "لم تحدث" وأعد المحاولة.
</Warning>

<Note>
  أرسل ترويسة `Idempotency-Key` لمنع تكرار إعادات المحاولة بأمان.
</Note>

## نقاط النهاية

| نقطة النهاية                    | النطاق              |
| ------------------------------- | ------------------- |
| `GET /v1/auth/verify`           | أي                  |
| `POST /v1/auth/rotate-key`      | أي                  |
| `GET /v1/balance/:discordId`    | `balance:read`      |
| `POST /v1/deduct`               | `deduct:create`     |
| `POST /v1/add`                  | `credit:create`     |
| `POST /v1/transfer`             | `transfer:create`   |
| `GET /v1/transactions` و `/:id` | `transactions:read` |
| `GET /v1/webhooks/events`       | `transactions:read` |

## الحدود

* تنتهي صلاحية طلبات التأكيد بعد **10 دقائق** — عامِل غير المؤكَّد منها كأنه مهجور
* `amount` يجب أن يكون عدداً صحيحاً موجباً
* `metadata` محدودة بـ 10 مفاتيح
* سقوف المعاملة الواحدة والحجم اليومي يضبطها طاقم فيتوكس، وتظهر للقراءة فقط في تبويب الإعدادات

## قائمة الأمان

<AccordionGroup>
  <Accordion title="أبقِ الأسرار على الخادم" icon="lock">
    مفتاح API وسرّ التوقيع لا مكان لهما في كود العميل إطلاقاً. دوّر أيّاً منهما فوراً إن تسرّب.
  </Accordion>

  <Accordion title="تحقّق من كل webhook" icon="signature">
    افحص التوقيع مقابل الجسم الخام، وارفض ما مضى عليه أكثر من \~5 دقائق.
  </Accordion>

  <Accordion title="سوِّ عند completed فقط" icon="circle-check">
    لا تسلّم أبداً بناءً على رد `/deduct` — الخصم ليس نهائياً حتى `confirmation.completed`.
  </Accordion>

  <Accordion title="أقل صلاحية ممكنة" icon="key">
    اطلب النطاقات التي تستخدمها فعلاً فقط، وفعّل قائمة عناوين IP المسموح بها.
  </Accordion>
</AccordionGroup>

## استكشاف الأخطاء

<AccordionGroup>
  <Accordion title="كل استدعاء يُعيد خطأ عدم التصريح">
    انقضت عضوية مالك المفتاح. تُفحَص عند كل استدعاء، لا عند الإصدار فقط.
  </Accordion>

  <Accordion title="فقدتُ مفتاحي">
    لا يمكن استعادته — لا يُخزَّن إلا تجزئته. دوّره للحصول على واحد جديد.
  </Accordion>

  <Accordion title="توقيعات webhook تفشل بعد التدوير">
    اقبل السرَّين خلال فترة التداخل البالغة 24 ساعة.
  </Accordion>

  <Accordion title="خصم لا يكتمل أبداً">
    المستخدم لم يوافق عليه. تنتهي طلبات التأكيد بعد 10 دقائق.
  </Accordion>

  <Accordion title="لا تصل أي webhooks">
    المشروع يحتاج رابط استدعاء وسرّ توقيع معاً. بواحد منهما فقط لا يُسلَّم شيء.
  </Accordion>

  <Accordion title="وصل Vito أقل مما خصمت">
    هذه رسوم التسوية. استخدم مبالغ 5 Vito أو أقل لتجنّبها، أو احسبها ضمن تسعيرك.
  </Accordion>

  <Accordion title="402 VITO_INSUFFICIENT_OWNER_FUNDS">
    `/v1/add` يُموَّل من رصيدك أنت، ولا يُنشأ من العدم. اشحن رصيدك.
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="Vito" icon="coins" href="/ar/members/vito">
    الأرصدة، ورمز PIN، والرسوم.
  </Card>

  <Card title="طلبات الدفع" icon="receipt" href="/ar/account/payment-requests">
    ما يراه المستخدم عندما تخصم منه.
  </Card>
</CardGroup>
