> ## 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 और खरीद

> अनुमोदित ऐप्स को PIN पुष्टि के साथ आपके Vito को चार्ज करने दें, और अपने Purchases पृष्ठ से भुगतान अनुरोध प्रबंधित करें।

<Info>
  **Silver** या उससे ऊपर की सदस्यता ज़रूरी है — आवेदन करने के लिए भी और हर प्रमाणित कॉल के लिए भी। अगर कुंजी के मालिक की सदस्यता समाप्त हो जाए, तो दोबारा सदस्यता लेने तक प्रोजेक्ट फ़्रीज़ रहता है।
</Info>

एक REST API जो आपके ऐप्लिकेशन को Discord के भीतर से किसी उपयोगकर्ता के [Vito](/hi/members/vito) बैलेंस के साथ काम करने देता है — उसे पढ़ना, उससे राशि लेना, उसमें जोड़ना, या उपयोगकर्ताओं के बीच स्थानांतरित करना। सभी एंडपॉइंट JSON लौटाते हैं और `/v1` के अंतर्गत वर्ज़न किए गए हैं।

<Warning>
  **Vito कभी असली पैसे में नहीं बदलता और न ही उससे आता है।** यह केवल Vetox बैलेंस के बीच ही चलता है।
</Warning>

## पहुँच प्राप्त करना

पहुँच **हर प्रोजेक्ट के लिए अलग से** दी जाती है। चारों चीज़ें चाहिए:

<Steps>
  <Step title="सक्रिय सदस्यता, Silver या उससे ऊपर">
    हर कॉल पर जाँची जाती है, सिर्फ़ स्वीकृति के समय नहीं।
  </Step>

  <Step title="स्वीकृत डेवलपर आवेदन">
    आपके डैशबोर्ड के Vito API पेज से भेजा जाता है। Vetox टीम इसकी समीक्षा हाथ से करती है।
  </Step>

  <Step title="स्वीकार की गई API डेवलपर शर्तें">
    आवेदन भेजते समय ही स्वीकार की जाती हैं।
  </Step>

  <Step title="आपके प्रोजेक्ट को जिन scopes की ज़रूरत है">
    आपके विवरण के आधार पर Vetox टीम द्वारा दिए जाते हैं।
  </Step>
</Steps>

<Tip>
  आप क्या बना रहे हैं और कुंजी कैसे संभालेंगे, यह ठोस रूप से लिखें। अस्पष्ट आवेदन ही अस्वीकार होते हैं।
</Tip>

### Scopes

| Scope               | अनुमति देता है                                 |
| ------------------- | ---------------------------------------------- |
| `balance:read`      | किसी उपयोगकर्ता का Vito बैलेंस पढ़ना           |
| `deduct:create`     | किसी उपयोगकर्ता के बैलेंस से राशि लेना         |
| `credit:create`     | अपने ही बैलेंस से किसी उपयोगकर्ता को Vito देना |
| `transfer:create`   | दो उपयोगकर्ताओं के बीच Vito स्थानांतरित करना   |
| `transactions:read` | अपने प्रोजेक्ट के लेनदेन देखना और पढ़ना        |

## प्रमाणीकरण

अपनी गुप्त कुंजी Bearer टोकन के रूप में भेजें:

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

दो वैकल्पिक परतें प्रोजेक्ट को और मज़बूत बनाती हैं:

* **IP अनुमति सूची** — कॉल को कुछ निश्चित सर्वर IP तक सीमित करती है
* **दर सीमाएँ** — प्रति-प्रोजेक्ट सीमाएँ, जो मालिक की सदस्यता श्रेणी के साथ बढ़ती हैं

### कुंजियाँ, रोटेशन और भंडारण

<Warning>
  **आपकी कुंजी और हस्ताक्षर सीक्रेट ठीक एक बार दिखाए जाते हैं।** स्वीकृति के बाद उन्हें API कुंजी टैब में देखने के लिए आपके पास **7 दिन की अवधि** होती है। Vetox सिर्फ़ एक हैश रखता है और उन्हें दोबारा नहीं दिखा सकता — यह अवधि चूक गए तो नई कुंजी के लिए रोटेशन करना होगा।
</Warning>

* इसे **केवल सर्वर पर** रखें — जिसके पास यह है, वह आपके उपयोगकर्ताओं से राशि ले सकता है
* रोटेशन API कुंजी टैब से करें। पुरानी कुंजी **24 घंटे** की छूट अवधि तक काम करती रहती है, ताकि आप बिना रुकावट तैनाती कर सकें
* webhook हस्ताक्षर सीक्रेट अलग से रोटेट होता है और उसकी अपनी 24 घंटे की अतिव्यापी अवधि होती है
* लीक होने पर तुरंत रोटेशन करें

## किसी उपयोगकर्ता से राशि लेना

<Warning>
  **अकेली कुंजी किसी उपयोगकर्ता के Vito को हिला नहीं सकती।** हर कटौती के लिए उपयोगकर्ता को `vetox.io` पर अपने वॉलेट PIN से मंज़ूरी देनी होती है — न आपके ऐप के भीतर, न Discord के भीतर।
</Warning>

<Steps>
  <Step title="आपका ऐप POST /v1/deduct कॉल करता है">
    उपयोगकर्ता, राशि, मूल `guildId` और वस्तु के विवरण के साथ।
  </Step>

  <Step title="Vito एक confirmUrl लौटाता है">
    एक लंबित पुष्टि, जो **10 मिनट** तक वैध रहती है। उपयोगकर्ता को DM भी जाता है।
  </Step>

  <Step title="उपयोगकर्ता अपने PIN से मंज़ूरी देता है">
    `vetox.io` पर।
  </Step>

  <Step title="Vito निपटान करता है और सूचित करता है">
    बैलेंस से कटौती होती है, लेनदेन दर्ज होता है, और यदि आपने कॉन्फ़िगर किया है तो हस्ताक्षरित webhook भेजा जाता है।
  </Step>

  <Step title="आपका ऐप सत्यापित करके पूरा करता है">
    हस्ताक्षर जाँचें, फिर सामग्री खोलें या वस्तु सौंपें।
  </Step>
</Steps>

<Warning>
  **अपनी कार्रवाई केवल `confirmation.completed` पर पूरी करें** — कभी भी `/deduct` की प्रतिक्रिया पर नहीं। उस समय कटौती अंतिम नहीं होती।
</Warning>

### अनुरोध पैरामीटर — `/v1/deduct`

| फ़ील्ड        | आवश्यक  | टिप्पणी                                                                          |
| ------------- | ------- | -------------------------------------------------------------------------------- |
| `discordId`   | **हाँ** | उपयोगकर्ता का Discord ID — 17–20 अंकों का snowflake                              |
| `amount`      | **हाँ** | धनात्मक पूर्णांक                                                                 |
| `guildId`     | **हाँ** | वह Discord सर्वर जहाँ से कटौती शुरू होती है। हर कटौती किसी सर्वर से ही आनी चाहिए |
| `reason`      | नहीं    | अधिकतम 256 अक्षर। उपयोगकर्ता को दिखता है और webhook में लौटाया जाता है           |
| `merchantRef` | नहीं    | आपका अपना संदर्भ, अधिकतम 128 अक्षर। webhook को अपने रिकॉर्ड से मिलाने के लिए     |
| `product`     | नहीं    | `{ type, name, description?, imageUrl? }` — पुष्टि पेज और DM में दिखता है        |
| `imageUrl`    | नहीं    | `https://` होना चाहिए                                                            |
| `metadata`    | नहीं    | अधिकतम **10** स्ट्रिंग कुंजी/मान जोड़े, ज्यों के त्यों आगे भेजे जाते हैं         |

## किसी उपयोगकर्ता को Vito देना

`POST /v1/add` किसी उपयोगकर्ता को **आपके अपने बैलेंस से** Vito देता है — इनाम या धनवापसी के लिए। `guildId` और `product` को छोड़कर वही फ़ील्ड जो `/deduct` में हैं।

<Note>
  कटौती के विपरीत, जोड़ने में **कोई पुष्टि चरण नहीं होता** — निपटान तुरंत हो जाता है। इसके लिए `credit:create` scope और पर्याप्त बैलेंस चाहिए, वरना कॉल **402 `VITO_INSUFFICIENT_OWNER_FUNDS`** लौटाता है।
</Note>

## शुल्क

हर कटौती प्लेटफ़ॉर्म शुल्क घटाकर आपको निपटाई जाती है — वही दर सूची जो ऐप के भीतर Vito स्थानांतरण पर लागू होती है, और आधार **आपकी** सदस्यता श्रेणी है:

| आपकी सदस्यता         | शुल्क |
| -------------------- | ----- |
| Normal, Silver, Gold | 7%    |
| Platinum             | 6%    |
| Diamond              | 5%    |

<Note>
  **5 Vito या उससे कम की राशि पर कोई शुल्क नहीं**, और `/v1/add` से दी गई राशि पर कभी शुल्क नहीं लगता।
</Note>

## Webhooks

सेटिंग्स टैब में एक या अधिक `https` कॉलबैक URL जोड़ें। जब भी कोई पुष्टि अंतिम स्थिति तक पहुँचती है, Vito एक हस्ताक्षरित `POST` भेजता है।

<Warning>
  webhooks तभी भेजे जाते हैं जब आपके प्रोजेक्ट में कॉलबैक URL **और** हस्ताक्षर सीक्रेट **दोनों** हों। सीक्रेट (`whsec_…`) को API कुंजी टैब से एक ही बार देखा जा सकता है।
</Warning>

### हस्ताक्षर सत्यापित करना

हर डिलीवरी के साथ `X-Vito-Signature` हेडर आता है:

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

हर डिलीवरी के साथ दो और हेडर आते हैं — `X-Vito-Event-Id` को डुप्लिकेट हटाने की कुंजी बनाएँ, क्योंकि पुनः प्रयास वही id दोबारा भेजता है:

| हेडर                | इसमें होता है                                     |
| ------------------- | ------------------------------------------------- |
| `X-Vito-Event-Id`   | इस ईवेंट का स्थिर id — हर पुनः प्रयास में एक जैसा |
| `X-Vito-Event-Type` | जैसे `confirmation.completed`                     |

<Warning>
  **हस्ताक्षर सीक्रेट के रोटेशन के दौरान हेडर में एक से अधिक हस्ताक्षर आते हैं**, सबसे नया पहले:

  ```text theme={null}
  X-Vito-Signature: ts=<unix>;h1=<नया>;h1=<पुराना>
  ```

  यदि **कोई भी** `h1` मेल खाए तो डिलीवरी स्वीकार करें। केवल पहला पढ़ने वाला सत्यापक नया सीक्रेट तैनात करने तक हर webhook अस्वीकार करेगा — और यही 24 घंटे की अतिव्यापी अवधि के पूरे उद्देश्य को व्यर्थ कर देता है।
</Warning>

अपने हस्ताक्षर सीक्रेट से `<ts>:<rawBody>` पर HMAC दोबारा निकालें और स्थिर समय में तुलना करें।

```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    | इस एंडपॉइंट के लिए ज़रूरी scope कुंजी में नहीं है          |
| `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    | Vetox टीम ने निलंबित किया                                  |
| `VITO_PROJECT_BANNED`                 | 403    | Vetox टीम ने प्रतिबंधित किया                               |
| `VITO_USER_BLACKLISTED`               | 403    | उपयोगकर्ता Vito संचालन से वंचित है                         |
| `VITO_ACCOUNT_LOCKED`                 | 403    | असफल PIN प्रयासों के बाद उपयोगकर्ता का वॉलेट लॉक है        |
| `VITO_USER_NOT_FOUND`                 | 404    | उस Discord ID के लिए कोई 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      |
| Silver या Gold      | 180        | 5,000      |
| Platinum या Diamond | 600        | 15,000     |

आपकी प्रति-मिनट सीमा की आधी, कम से कम 30, एक प्रति-IP सीमा भी लागू होती है।

<Warning>
  भारी लोड में **लिखने वाले एंडपॉइंट बंद होकर विफल होते हैं** — दोहरे ख़र्च का जोखिम लेने के बजाय कटौती अस्वीकार कर दी जाती है। पढ़ने वाले एंडपॉइंट खुले होकर विफल होते हैं। अस्वीकृत लेखन को "हुआ ही नहीं" मानकर दोबारा भेजें।
</Warning>

<Note>
  पुनः प्रयासों को सुरक्षित ढंग से डुप्लिकेट-मुक्त रखने के लिए `Idempotency-Key` हेडर भेजें।
</Note>

## एंडपॉइंट

| एंडपॉइंट                         | Scope               |
| -------------------------------- | ------------------- |
| `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 कुंजियों तक सीमित है
* प्रति-लेनदेन और दैनिक सीमाएँ Vetox टीम तय करती है; वे सेटिंग्स टैब में केवल-पढ़ने के रूप में दिखती हैं

## सुरक्षा जाँच-सूची

<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">
    केवल वही scopes माँगें जो आप सचमुच उपयोग करते हैं, और IP अनुमति सूची चालू रखें।
  </Accordion>
</AccordionGroup>

## समस्या निवारण

<AccordionGroup>
  <Accordion title="हर कॉल अनधिकृत लौटाती है">
    मालिक की सदस्यता समाप्त हो चुकी है। यह हर कॉल पर दोबारा जाँची जाती है।
  </Accordion>

  <Accordion title="मेरी कुंजी खो गई">
    इसे वापस नहीं पाया जा सकता — केवल हैश संग्रहीत होता है। नई पाने के लिए रोटेट करें।
  </Accordion>

  <Accordion title="रोटेशन के बाद webhook हस्ताक्षर विफल हो रहे हैं">
    24 घंटे की अतिव्यापी अवधि में दोनों सीक्रेट स्वीकार करें।
  </Accordion>

  <Accordion title="कोई कटौती कभी पूरी नहीं होती">
    उपयोगकर्ता ने मंज़ूरी नहीं दी। पुष्टियाँ 10 मिनट बाद समाप्त हो जाती हैं।
  </Accordion>

  <Accordion title="कोई webhook नहीं आता">
    प्रोजेक्ट को कॉलबैक URL और हस्ताक्षर सीक्रेट दोनों चाहिए। किसी एक के होने पर कुछ भी नहीं भेजा जाता।
  </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="/hi/members/vito">
    बैलेंस, PIN और शुल्क।
  </Card>

  <Card title="भुगतान अनुरोध" icon="receipt" href="/hi/account/payment-requests">
    जब आप राशि लेते हैं तो उपयोगकर्ता को क्या दिखता है।
  </Card>
</CardGroup>
