> ## 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 ve satın almalar

> Onaylı uygulamaların PIN onayıyla Vito'nuzdan ücret almasına izin verin ve Satın Almalar sayfanızdan ödeme isteklerini yönetin.

<Info>
  **Silver** veya üzeri bir üyelik gerektirir — hem başvurmak hem de her kimliği doğrulanmış çağrı için. Anahtar sahibinin üyeliği sona ererse, yeniden abone olana kadar proje dondurulur.
</Info>

Uygulamanızın bir kullanıcının [Vito](/tr/members/vito) bakiyesiyle doğrudan Discord içinden çalışmasını sağlayan bir REST API — okuma, tahsilat, alacak kaydetme veya kullanıcılar arasında aktarma. Tüm uç noktalar JSON döner ve `/v1` altında sürümlenir.

<Warning>
  **Vito asla gerçek paraya dönüşmez, gerçek paradan da gelmez.** Yalnızca Vetox bakiyeleri arasında hareket eder.
</Warning>

## Erişim alma

Erişim **proje bazında** verilir. Dördüne birden ihtiyacınız var:

<Steps>
  <Step title="Aktif bir üyelik, Silver veya üzeri">
    Yalnızca onay anında değil, her çağrıda kontrol edilir.
  </Step>

  <Step title="Onaylanmış bir geliştirici başvurusu">
    Panelinizdeki Vito API sayfasından gönderilir. Vetox ekibi tarafından elle incelenir.
  </Step>

  <Step title="Kabul edilmiş API Geliştirici Şartları">
    Başvuruyu gönderirken onaylanır.
  </Step>

  <Step title="Projenizin ihtiyaç duyduğu scope'lar">
    Açıklamanıza göre Vetox ekibi tarafından verilir.
  </Step>
</Steps>

<Tip>
  Ne inşa ettiğinizi ve anahtarı nasıl saklayacağınızı somut yazın. Reddedilenler, muğlak başvurulardır.
</Tip>

### Scope'lar

| Scope               | İzin verdiği                                                   |
| ------------------- | -------------------------------------------------------------- |
| `balance:read`      | Bir kullanıcının Vito bakiyesini okumak                        |
| `deduct:create`     | Bir kullanıcının bakiyesinden tahsilat yapmak                  |
| `credit:create`     | Kendi bakiyenizden finanse ederek bir kullanıcıya Vito eklemek |
| `transfer:create`   | İki kullanıcı arasında Vito taşımak                            |
| `transactions:read` | Projenizin işlemlerini listelemek ve okumak                    |

## Kimlik doğrulama

Gizli anahtarınızı Bearer token olarak gönderin:

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

İsteğe bağlı iki katman projeyi daha da sağlamlaştırır:

* **IP izin listesi** — çağrıları belirli sunucu IP'leriyle sınırlar
* **Hız limitleri** — sahibin üyelik seviyesiyle birlikte yükselen proje bazlı tavanlar

### Anahtarlar, döndürme ve saklama

<Warning>
  **Anahtarınız ve imza gizli anahtarınız tam olarak bir kez gösterilir.** Onaydan sonra, bunları API anahtarları sekmesinde açığa çıkarmak için **7 günlük bir pencereniz** olur. Vetox yalnızca bir özet saklar ve bunları tekrar gösteremez — pencereyi kaçırırsanız döndürme yapmanız gerekir.
</Warning>

* Yalnızca **sunucu tarafında** tutun — anahtarı elinde tutan herkes kullanıcılarınızdan tahsilat yapabilir
* API anahtarları sekmesinden döndürün. Önceki anahtar **24 saatlik bir tolerans süresi** boyunca çalışmaya devam eder, böylece kesintisiz dağıtım yapabilirsiniz
* Webhook imza gizli anahtarı ayrı döndürülür ve kendi 24 saatlik örtüşmesi vardır
* Sızarsa hemen döndürün

## Bir kullanıcıdan tahsilat

<Warning>
  **Anahtarınız tek başına bir kullanıcının Vito'sunu hareket ettiremez.** Her tahsilat, kullanıcının cüzdan PIN'iyle `vetox.io` üzerinde onay vermesini gerektirir — asla uygulamanızın içinde, asla Discord'un içinde değil.
</Warning>

<Steps>
  <Step title="Uygulamanız POST /v1/deduct çağırır">
    Kullanıcı, tutar, kaynak `guildId` ve ürün ayrıntılarıyla.
  </Step>

  <Step title="Vito bir confirmUrl döner">
    **10 dakika** geçerli, bekleyen bir onay. Kullanıcıya ayrıca DM gönderilir.
  </Step>

  <Step title="Kullanıcı PIN'iyle onaylar">
    `vetox.io` üzerinde.
  </Step>

  <Step title="Vito mahsuplaşır ve bildirir">
    Bakiye düşülür, işlem kaydedilir ve yapılandırdıysanız imzalı bir webhook gönderilir.
  </Step>

  <Step title="Uygulamanız doğrular ve tamamlar">
    İmzayı kontrol edin, ardından içeriği açın veya ürünü teslim edin.
  </Step>
</Steps>

<Warning>
  **İşleminizi yalnızca `confirmation.completed` üzerine tamamlayın** — asla `/deduct` yanıtı üzerine değil. O noktada tahsilat henüz kesinleşmemiştir.
</Warning>

### İstek parametreleri — `/v1/deduct`

| Alan          | Zorunlu  | Notlar                                                                                        |
| ------------- | -------- | --------------------------------------------------------------------------------------------- |
| `discordId`   | **Evet** | Kullanıcının Discord kimliği — 17–20 haneli bir snowflake                                     |
| `amount`      | **Evet** | Pozitif tam sayı                                                                              |
| `guildId`     | **Evet** | Tahsilatın kaynaklandığı Discord sunucusu. Her tahsilat bir sunucudan gelmelidir              |
| `reason`      | Hayır    | En fazla 256 karakter. Kullanıcıya gösterilir ve webhook'ta geri döner                        |
| `merchantRef` | Hayır    | Kendi referansınız, en fazla 128 karakter. Webhook'u kayıtlarınızla eşleştirmek için kullanın |
| `product`     | Hayır    | `{ type, name, description?, imageUrl? }` — onay sayfasında ve DM'de görünür                  |
| `imageUrl`    | Hayır    | `https://` olmalıdır                                                                          |
| `metadata`    | Hayır    | En fazla **10** metin anahtar/değer çifti, olduğu gibi iletilir                               |

## Bir kullanıcıya alacak kaydetme

`POST /v1/add`, bir kullanıcıya **kendi bakiyenizden** Vito ekler — ödüller veya iadeler için. `guildId` ve `product` dışında `/deduct` ile aynı alanlar.

<Note>
  Tahsilatın aksine, alacak kaydının **onay adımı yoktur** — anında mahsuplaşır. `credit:create` scope'unu ve yeterli bakiyeyi gerektirir; aksi hâlde çağrı **402 `VITO_INSUFFICIENT_OWNER_FUNDS`** döner.
</Note>

## Ücretler

Her tahsilat, platform ücreti düşülerek size aktarılır — uygulama içi Vito transferleriyle aynı tarife üzerinden ve **sizin** üyelik seviyenize göre:

| Üyeliğiniz           | Ücret |
| -------------------- | ----- |
| Normal, Silver, Gold | %7    |
| Platinum             | %6    |
| Diamond              | %5    |

<Note>
  **5 Vito ve altındaki tutarlar ücretsizdir**, `/v1/add` üzerinden yapılan alacak kayıtları ise her zaman ücretsizdir.
</Note>

## Webhook'lar

Ayarlar sekmesinde bir veya daha fazla `https` geri çağırma adresi ekleyin. Bir onay nihai duruma ulaştığında Vito imzalı bir `POST` gönderir.

<Warning>
  Webhook'lar yalnızca projenizde **hem** bir geri çağırma adresi **hem de** bir imza gizli anahtarı varsa gönderilir. Gizli anahtarı (`whsec_…`) API anahtarları sekmesinden bir kez açığa çıkarın.
</Warning>

### İmzayı doğrulama

Her teslimat bir `X-Vito-Signature` başlığı taşır:

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

Her teslimata iki başlık daha eşlik eder — `X-Vito-Event-Id`'yi yineleme önleme anahtarı olarak kullanın, çünkü yeniden deneme aynı kimliği tekrar gönderir:

| Başlık              | İçerir                                                   |
| ------------------- | -------------------------------------------------------- |
| `X-Vito-Event-Id`   | Bu olay için sabit kimlik — tüm yeniden denemelerde aynı |
| `X-Vito-Event-Type` | Örneğin `confirmation.completed`                         |

<Warning>
  **İmza gizli anahtarı döndürülürken başlık birden fazla imza taşır**, en yenisi başta:

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

  `h1` değerlerinden **herhangi biri** eşleşiyorsa teslimatı kabul edin. Yalnızca ilkini okuyan bir doğrulayıcı, yeni gizli anahtarı dağıtana kadar her webhook'u reddeder — ki bu da 24 saatlik örtüşmenin bütün amacını ortadan kaldırır.
</Warning>

HMAC'i `<ts>:<rawBody>` üzerinden imza gizli anahtarınızla yeniden hesaplayın ve sabit sürede karşılaştırın.

```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 ayrıştırma veya ara katman onu yeniden yazmadan önce, **ham gövdeye** karşı doğrulayın.
</Warning>

### Olaylar

Beş olay türü, hepsi aynı yük yapısını paylaşır. Sonucu `data.status` taşır.

| Olay                     | Anlamı                                                                                     |
| ------------------------ | ------------------------------------------------------------------------------------------ |
| `confirmation.completed` | Onaylandı ve tahsil edildi. `transactionId` taşır. **İşleminizi burada tamamlayın**        |
| `confirmation.failed`    | Tamamlanamadı — yetersiz bakiye veya dahili bir hata. `failureReason` taşır                |
| `confirmation.expired`   | 10 dakika içinde onaylanmadı. Hiç Vito hareket etmedi                                      |
| `confirmation.cancelled` | Kullanıcı iptal etti. Hiç Vito hareket etmedi                                              |
| `credit.completed`       | Sahip tarafından finanse edilen bir `/add` mahsuplaştı. Anında tetiklenir — onay adımı yok |

<Note>
  Webhook'lar **artan beklemeyle 5 kez** yeniden denenir. Hızlıca 2xx ile yanıt verin ve teslimatınızı eşzamansız yapın.
</Note>

## Hata kodları

Her yanıt bir zarf içindedir. Başarı `data`, hata ise `error` taşır; ikisi birden asla olmaz:

```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>
  **Her kod `VITO_` ön ekiyle başlar.** Tam dizeyi karşılaştırın — yalın bir `RATE_LIMITED` veya `FORBIDDEN` yanıtta asla görünmez.
</Warning>

| Kod                                   | Durum | Anlamı                                                                |
| ------------------------------------- | ----- | --------------------------------------------------------------------- |
| `VITO_VALIDATION_ERROR`               | 400   | Bir alan eksik veya hatalı biçimde                                    |
| `VITO_INVALID_AMOUNT`                 | 400   | `amount` pozitif bir tam sayı değil                                   |
| `VITO_AMOUNT_LIMIT_EXCEEDED`          | 400   | İşlem başına tavanınızın üzerinde                                     |
| `VITO_DAILY_VOLUME_EXCEEDED`          | 400   | Bu çağrı günlük hacim tavanınızı aşardı                               |
| `VITO_SELF_TRANSFER`                  | 400   | Gönderen ve alıcı aynı kullanıcı                                      |
| `VITO_INVALID_API_KEY`                | 401   | Eksik, hatalı, iptal edilmiş veya bilinmeyen anahtar                  |
| `VITO_INSUFFICIENT_FUNDS`             | 402   | Kullanıcının bakiyesi tahsilatı karşılamıyor                          |
| `VITO_INSUFFICIENT_OWNER_FUNDS`       | 402   | **Sizin** bakiyeniz bir `/add`'i finanse etmeye yetmiyor              |
| `VITO_INSUFFICIENT_SCOPE`             | 403   | Anahtarda uç noktanın gerektirdiği scope yok                          |
| `VITO_IP_NOT_ALLOWED`                 | 403   | Çağıran IP izin listesinde değil                                      |
| `VITO_OWNER_MEMBERSHIP_INACTIVE`      | 403   | Sahibin üyeliği sona erdi — yenilenene kadar donduruldu               |
| `VITO_GUILD_NOT_ALLOWED`              | 403   | `guildId` projenin izinli sunucular listesinde değil                  |
| `VITO_TOS_NOT_ACCEPTED`               | 403   | Geliştirici şartları kabul edilmedi veya daha yeni bir sürüm bekliyor |
| `VITO_PROJECT_FROZEN`                 | 403   | Donduruldu — genellikle sahibin üyeliğinin sona ermesi nedeniyle      |
| `VITO_PROJECT_SUSPENDED`              | 403   | Vetox ekibi tarafından askıya alındı                                  |
| `VITO_PROJECT_BANNED`                 | 403   | Vetox ekibi tarafından yasaklandı                                     |
| `VITO_USER_BLACKLISTED`               | 403   | Kullanıcı Vito işlemlerinden men edilmiş                              |
| `VITO_ACCOUNT_LOCKED`                 | 403   | Başarısız PIN denemelerinden sonra kullanıcının cüzdanı kilitli       |
| `VITO_USER_NOT_FOUND`                 | 404   | Bu Discord kimliği için Vito hesabı yok                               |
| `VITO_CONFIRMATION_NOT_FOUND`         | 404   | Bilinmeyen onay belirteci                                             |
| `VITO_IDEMPOTENCY_CONFLICT`           | 409   | Aynı `Idempotency-Key`, farklı gövde                                  |
| `VITO_IDEMPOTENCY_IN_PROGRESS`        | 409   | Aynı istek hâlâ işleniyor — kısa süre sonra tekrar deneyin            |
| `VITO_CONFIRMATION_ALREADY_PROCESSED` | 409   | Bu onay zaten nihai bir duruma ulaştı                                 |
| `VITO_KEY_ROTATION_IN_PROGRESS`       | 409   | Zaten bir döndürme sürüyor                                            |
| `VITO_CONFIRMATION_EXPIRED`           | 410   | 10 dakikalık pencere doldu                                            |
| `VITO_RATE_LIMITED`                   | 429   | Hızınızı düşürüp tekrar deneyin                                       |
| `VITO_INTERNAL_ERROR`                 | 500   | Bizim tarafımızda beklenmeyen bir arıza                               |

## Hız limitleri

| Sahibin üyeliği       | Dakikada | Saatte |
| --------------------- | -------- | ------ |
| Yok                   | 60       | 1.000  |
| Silver veya Gold      | 180      | 5.000  |
| Platinum veya Diamond | 600      | 15.000 |

Ayrıca dakikalık kotanızın yarısına eşit, en az 30 olan bir IP başına limit vardır.

<Warning>
  Yük altında **yazma uç noktaları kapalı biçimde başarısız olur** — çifte harcama riskine girmek yerine tahsilat reddedilir. Okuma uç noktaları açık biçimde başarısız olur. Reddedilen bir yazmayı "gerçekleşmedi" kabul edip yeniden deneyin.
</Warning>

<Note>
  Yeniden denemeleri güvenle yinelemesiz kılmak için bir `Idempotency-Key` başlığı gönderin.
</Note>

## Uç noktalar

| Uç nokta                         | Scope               |
| -------------------------------- | ------------------- |
| `GET /v1/auth/verify`            | herhangi biri       |
| `POST /v1/auth/rotate-key`       | herhangi biri       |
| `GET /v1/balance/:discordId`     | `balance:read`      |
| `POST /v1/deduct`                | `deduct:create`     |
| `POST /v1/add`                   | `credit:create`     |
| `POST /v1/transfer`              | `transfer:create`   |
| `GET /v1/transactions` ve `/:id` | `transactions:read` |
| `GET /v1/webhooks/events`        | `transactions:read` |

## Sınırlar

* Onaylar **10 dakika** sonra sona erer — onaylanmamış talepleri terk edilmiş sayın
* `amount` pozitif bir tam sayı olmalıdır
* `metadata` 10 anahtarla sınırlıdır
* İşlem başına ve günlük tavanları Vetox ekibi belirler; ayarlar sekmesinde salt okunur görünür

## Güvenlik kontrol listesi

<AccordionGroup>
  <Accordion title="Gizli anahtarları sunucuda tutun" icon="lock">
    API anahtarı ve imza gizli anahtarı asla istemci koduna ait değildir. Herhangi biri sızarsa hemen döndürün.
  </Accordion>

  <Accordion title="Her webhook'u doğrulayın" icon="signature">
    İmzayı ham gövdeye karşı kontrol edin ve \~5 dakikadan eski teslimatları reddedin.
  </Accordion>

  <Accordion title="Yalnızca completed üzerine mahsuplaşın" icon="circle-check">
    Asla `/deduct` yanıtına dayanarak teslim etmeyin — tahsilat ancak `confirmation.completed` ile kesinleşir.
  </Accordion>

  <Accordion title="En az ayrıcalık" icon="key">
    Yalnızca gerçekten kullandığınız scope'ları isteyin ve IP izin listesini etkinleştirin.
  </Accordion>
</AccordionGroup>

## Sorun giderme

<AccordionGroup>
  <Accordion title="Her çağrı yetkisiz dönüyor">
    Sahibin üyeliği sona ermiş. Her çağrıda yeniden kontrol edilir.
  </Accordion>

  <Accordion title="Anahtarımı kaybettim">
    Geri getirilemez — yalnızca bir özet saklanır. Yeni bir tane almak için döndürün.
  </Accordion>

  <Accordion title="Döndürmeden sonra webhook imzaları başarısız oluyor">
    24 saatlik örtüşme boyunca her iki gizli anahtarı da kabul edin.
  </Accordion>

  <Accordion title="Bir tahsilat hiç tamamlanmıyor">
    Kullanıcı onaylamadı. Onaylar 10 dakika sonra sona erer.
  </Accordion>

  <Accordion title="Hiç webhook gelmiyor">
    Bir projeye hem geri çağırma adresi hem imza gizli anahtarı gerekir. Yalnızca biri varsa hiçbir şey teslim edilmez.
  </Accordion>

  <Accordion title="Tahsil ettiğimden daha az Vito geldi">
    Bu mahsuplaşma ücretidir. Kaçınmak için 5 Vito ve altı tutarlar kullanın veya fiyatınıza dâhil edin.
  </Accordion>

  <Accordion title="402 VITO_INSUFFICIENT_OWNER_FUNDS">
    `/v1/add` kendi bakiyenizden finanse edilir, yoktan yaratılmaz. Bakiyenizi yükleyin.
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="Vito" icon="coins" href="/tr/members/vito">
    Bakiyeler, PIN ve ücretler.
  </Card>

  <Card title="Ödeme talepleri" icon="receipt" href="/tr/account/payment-requests">
    Ondan tahsilat yaptığınızda kullanıcının gördüğü şey.
  </Card>
</CardGroup>
