# blockwallets yerel REST API

> blockwallets yerel REST API: Bearer anahtarları, idempotent ref'li ABD senti cinsinden faturalar, deposit hesapları, HMAC-SHA256 imzalı webhook'lar, events ve yeniden gönderim.
>
> HTML: https://blockwallets.io/docs/api?lang=tr · English: https://blockwallets.io/docs/api.md?lang=en

## Yerel REST API

Yerel API, blockwallets'ın kendi REST arayüzüdür: ABD senti cinsinden fiyatlanan faturalar, sipariş başına idempotent bir `ref`, tüm ağları kapsayan statik deposit hesapları ve HMAC-SHA256 ile imzalanan webhook'lar. [Cryptomus uyumlu API](https://blockwallets.io/docs/cryptomus?lang=tr) ile aynı barındırılan ödeme sayfasında aynı faturaları, aynı ücret ve bakiyeyle oluşturur.

Anahtarlarınızı panelde “Geliştiriciler › Entegrasyon ve anahtarlar” altında kendiniz oluşturursunuz: bir Live ve bir Test anahtarı ile bunların webhook signing secret'ları. Her biri bir kez gösterilir; listede yalnızca öneki görünür. Hesabınızda iki adımlı doğrulama açıksa Live anahtarı oluşturmak veya yenilemek kod ister. Henüz satıcı hesabınız yok mu? [Erişim isteyin](https://blockwallets.io/?lang=tr#join). Zaten Cryptomus kullanıyor musunuz? [Cryptomus uyumlu API](https://blockwallets.io/docs/cryptomus?lang=tr)'ye bakın ([nasıl seçilir](https://blockwallets.io/docs?lang=tr#which)).

### Anahtarlar ve istekler

Temel URL `https://blockwallets.io`. İstekler ve yanıtlar JSON'dur. Her istek şunları taşır:

- `Authorization: Bearer bw_live_…` veya `Bearer bw_test_…`: önek modu belirler; bu yüzden bir Test anahtarı yalnızca Test faturalarını görür ve testnet'lerde çalışır

- `POST` isteklerinde `Content-Type: application/json`

- Anahtarları yalnızca sunucunuzda tutun, asla bir web sayfasında ya da uygulamada değil; biz yalnızca hash'lerini saklarız

Hatalar bir HTTP durumu ve `{"error": {"code": "…", "message": "…"}}` döndürür: 400 `invalid_request` (eksik ya da hatalı biçimli bir alan), 401 `unauthorized` (eksik, bilinmeyen ya da devre dışı anahtar), 404 `not_found`, 409 `conflict` (istek faturanın mevcut durumuyla çakışıyor), 422 `currency_unsupported`.

### Endpoint'ler

| Endpoint | Ne yapar |
| --- | --- |
| `GET /v1/networks` | Bu anahtarın modunda şu anda kabul edebileceğiniz ağlar: minimum, onaylar, tipik varış süresi ve ücret tahmini; fiyatlanan coin'lerde güncel kur da bulunur |
| `POST /v1/invoices` | Bir fatura oluşturur (201) ya da aynı `ref` için mevcut olanı döndürür (200) |
| `GET /v1/invoices?ref=…` | Faturayı kendi `ref` değerinizle sorgular |
| `GET /v1/invoices/:id` | Faturayı id ile sorgular |
| `POST /v1/invoices/:id/network` | Bir fatura için ağı kendiniz seçin (white-label ödeme sayfası): gösterilecek `address` ve `pay_amount` değerlerini döndürür |
| `POST /v1/invoices/:id/close` | Henüz hiç transfer görmemiş bekleyen bir faturayı kapatır |
| `POST /v1/deposit-accounts` | Bir müşterinin deposit hesabını açar (201) ya da getirir (200): her ağda kalıcı bir adres |
| `GET /v1/deposit-accounts?customer_ref=…` | Deposit hesabını `customer_ref` ile sorgular |
| `GET /v1/deposit-accounts/:id` | Deposit hesabını id ile sorgular |
| `GET /v1/deposits` | Bir hesabın depozitolarını listeler (`account_id` veya `customer_ref`, `limit` 1–200, varsayılan 50) |
| `GET /v1/deposits/:id` | Tek bir depozitoyu sorgular |
| `GET /v1/events` | Bir fatura ya da depozito için webhook gönderimleri (`invoice_id` veya `deposit_id`) |
| `POST /v1/events/:id/redeliver` | Bir webhook'u yeniden gönderir (202) |

Zinciri o anda kontrol etmek için fatura ya da deposit hesabı sorgusuna `?probe=1` ekleyin (en fazla 10 saniyede bir); aksi halde her dakika kontrol eden tarayıcımızın en son durumunu alırsınız.

### Fatura oluşturma POST /v1/invoices

Müşteri ödemeye geçtiğinde `POST /v1/invoices` çağırın ve yanıttaki `pay_url` adresine yönlendirin.

```curl
curl -X POST https://blockwallets.io/v1/invoices \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"ref":"order_1042","amount":4200,"title":"Order #1042",
       "return_url":"https://shop.example/cart","success_url":"https://shop.example/thanks?order=1042",
       "meta":{"user_id":42}}'
```

| Alan | Zorunlu | Açıklama |
| --- | --- | --- |
| `ref` | Evet | Sipariş numaranız: harf, rakam ve `_ . : -` içeren 1–64 karakter. Mod başına benzersizdir; aynı alanlarla aynı `ref` yeniden gönderilirse aynı fatura döner, farklı alanlarla 409 döner |
| `amount` | Evet | ABD senti cinsinden tam sayı tutar: `4200` = $42.00. Bir ağ seçildikten sonra ağ minimumunun altında olamaz |
| `title` | Evet | Müşterinin ödeme sayfasında gördüğü metin, en fazla 64 karakter |
| `return_url` | Evet | Ödeme sayfasındaki “Geri”nin gideceği yer; web sitesi alan adlarınızdan birinde olmalıdır |
| `success_url` | Hayır | Müşterinin ödemeden sonra gideceği yer; varsayılan `return_url` |
| `network` | Hayır | [Ağ tablosundan](https://blockwallets.io/docs/api?lang=tr#networks) bir ağ id'sini önceden seçer; müşterinin ödeme sayfasında seçmesi için boş bırakın |
| `customer_ref` | Hayır | Müşteri id'niz, en fazla 64 karakter, olduğu gibi geri döner |
| `lifetime` | Hayır | Saniye cinsinden ömür, 600 – 43200, varsayılan 3600 |
| `amount_rule` | Hayır | `"any"` = gelen her tutarı yükle (bakiye yüklemeleri): onaylanır onaylanmaz `paid`. Paneldeki “Ayarlar › Ödeme kuralları ve ücretler” bölümündeki “Tutar kuralı”nı kullanmak için boş bırakın |
| `accuracy_percent` | Hayır | Eksik ödemenin ne kadarı hâlâ ödenmiş sayılır, 0 – 5 (yüzde), varsayılan 0 |
| `subtract_percent` | Hayır | Platform ücretinin müşterinin ödediği payı, 0 – 100 (yüzde), `pay_amount`'a eklenir; panelin varsayılanı için boş bırakın |
| `payment_multiple` | Hayır | Eksik bir ödemenin aynı adrese tamamlanıp tamamlanamayacağı, varsayılan panelden gelir (siz değiştirmedikçe açık); `false`: ilk eksik transfer `wrong_amount` olarak biter |
| `meta` | Hayır | En fazla 2 KB'lık herhangi bir JSON nesnesi, sorgularda ve webhook'larda olduğu gibi geri döner |
| `currency` | Hayır | Yalnızca `USD` (varsayılan); başka bir değer 422 döndürür |

Her URL web sitesi alan adlarınızdan birinde olmalıdır (panel → “Geliştiriciler › Entegrasyon ve anahtarlar”). Yanıt aşağıdaki fatura nesnesidir; `network`, `address` ve `pay_amount` bir ağ seçildiğinde doldurulur.

### Fatura nesnesi

Id'ler `inv_` ile başlar. `amount` ABD senti cinsindendir; `pay_amount` ve `paid_amount` seçilen ağda ondalık dize olarak coin tutarlarıdır.

```json
{
  "id": "inv_01J8…",
  "ref": "order_1042",
  "mode": "live",
  "status": "pending",
  "amount": 4200,
  "currency": "USD",
  "title": "Order #1042",
  "meta": { "user_id": 42 },
  "network": null,
  "address": null,
  "pay_amount": null,
  "paid_amount": null,
  "payments": [],
  "pay_url": "https://blockwallets.io/pay/inv_01J8…",
  "return_url": "https://shop.example/cart",
  "success_url": "https://shop.example/thanks?order=1042",
  "created_at": "2026-11-03T08:00:00.000Z",
  "expires_at": "2026-11-03T09:00:00.000Z",
  "paid_at": null,
  "closed_at": null
}
```

| status | Anlamı | Ne yaparsınız |
| --- | --- | --- |
| `pending` | Ödeme bekleniyor | — |
| `confirming` | Bir transfer görüldü ve onaylanıyor, ya da eksik geldi ve hâlâ tamamlanabilir | — |
| `paid` | Ödendi | Siparişi gönderin / yükleyin |
| `paid_over` | Ödendi, fazla ödenmiş | Aynı; fazlalık bakiyenizdedir |
| `wrong_amount` | Tam tutardan az gelerek bitti (süre dolduğunda ya da `payment_multiple` false iken ilk eksik transferde) | Bakiye yükleme işleri gelen tutarı yükleyebilir (`paid_amount`; kurlu coin'lerde ayrıca `paid_cents`); mağazalar müşteriden kalanı ödemesini ister |
| `closed` | Hiçbir şey gelmeden süresi doldu ya da siz kapattınız | — (sonradan gelen para yine de yatırılır ve bildirilir) |

Diğer alanlar: `pay_url` (barındırılan ödeme sayfası), `payments` (her transfer; `txid`, `amount`, `confirmations` ve `confirmed` ile), `expires_at`, `paid_at`, `closed_at`; BTC, LTC, DOGE, BCH ve ağların kendi coin'lerinde ayrıca `rate` (coin başına ABD doları, 30 dakika sabit), `rate_locked_until` ve `paid_cents` (şimdiye kadar gelen tutar, ABD senti) bulunur.

### Ağlar

Id'yi `network` olarak gönderin. `GET /v1/networks` modunuzda şu anda açık olanları döndürür; bir ağ duraklatılabilir, bu yüzden koda sabitlemek yerine bunu okumayı tercih edin.

| network | Coin | Zincir | Minimum |
| --- | --- | --- | --- |
| `USDT_TRC20` | USDT | TRON | $1 |
| `USDT_BEP20` | USDT | BNB Chain | $1 |
| `USDC_BEP20` | USDC | BNB Chain | $1 |
| `USDT_ERC20` | USDT | Ethereum | $5 |
| `USDC_ERC20` | USDC | Ethereum | $5 |
| `USDC_BASE` | USDC | Base | $1 |
| `USDT_POLYGON` | USDT | Polygon | $1 |
| `USDC_POLYGON` | USDC | Polygon | $1 |
| `USDT_ARBITRUM` | USDT | Arbitrum | $1 |
| `USDC_ARBITRUM` | USDC | Arbitrum | $1 |
| `USDT_OPTIMISM` | USDT | Optimism | $1 |
| `USDC_OPTIMISM` | USDC | Optimism | $1 |
| `USDT_AVALANCHE` | USDT | Avalanche | $1 |
| `USDC_AVALANCHE` | USDC | Avalanche | $1 |
| `USDT_XLAYER` | USDT | X Layer | $1 |
| `USDC_XLAYER` | USDC | X Layer | $1 |
| `USD1_BEP20` | USD1 | BNB Chain | $1 |
| `FDUSD_BEP20` | FDUSD | BNB Chain | $1 |
| `DAI_ERC20` | DAI | Ethereum | $5 |
| `DAI_ARBITRUM` | DAI | Arbitrum | $1 |
| `DAI_BASE` | DAI | Base | $1 |
| `BTC` | BTC | Bitcoin | $5 |
| `LTC` | LTC | Litecoin | $1 |
| `DOGE` | DOGE | Dogecoin | $1 |
| `BCH` | BCH | Bitcoin Cash | $1 |
| `TRX` | TRX | TRON | $1 |
| `BNB` | BNB | BNB Chain | $1 |
| `ETH` | ETH | Ethereum | $5 |
| `ETH_BASE` | ETH | Base | $1 |
| `ETH_ARBITRUM` | ETH | Arbitrum | $1 |
| `ETH_OPTIMISM` | ETH | Optimism | $1 |
| `POL` | POL | Polygon | $1 |
| `AVAX` | AVAX | Avalanche | $1 |
| `OKB` | OKB | X Layer | $1 |
| `USDT_SOL` | USDT | Solana | $1 |
| `USDC_SOL` | USDC | Solana | $1 |
| `SOL` | SOL | Solana | $1 |
| `USDT_TON` | USDT | TON | $1 |
| `TON` | TON | TON | $1 |

### Deposit hesapları (statik adresler) POST /v1/deposit-accounts

`{"customer_ref": "user_42"}` ile `POST /v1/deposit-accounts`, o müşteriye her ağda kalıcı bir adres verir (tüm EVM zincirleri tek adresi paylaşır). Gönderdikleri her şey ABD doları olarak yatırılır ve her transfer için bir `deposit.credited` webhook'u gönderilir.

```curl
curl -X POST https://blockwallets.io/v1/deposit-accounts \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"customer_ref":"user_42"}'
```

```json
{
  "id": "dac_01J8…",
  "mode": "live",
  "customer_ref": "user_42",
  "deposit_url": "https://blockwallets.io/deposit/dac_01J8…",
  "min_amount": 100,
  "currency": "USD",
  "networks": [
    { "id": "USDT_TRC20", "chain": "tron", "token": "USDT", "address": "TXy4…8kQ2", "min_amount": 100, "confirmations": 1, … },
    { "id": "USDC_BASE", "chain": "base", "token": "USDC", "address": "0x5aE1…", "min_amount": 100, "confirmations": 20, … }
  ]
}
```

- `customer_ref`: harf, rakam ve `_ . : @ -` içeren 1–128 karakter; aynı değer her zaman aynı hesabı döndürür. Alan adlarınızda isteğe bağlı `return_url`

- Yanıtta `deposit_url` (adresleri, QR kodlarını ve son depozitoları gösteren barındırılan bir sayfa) ve `networks` (her biri için `id`, `address`, `min_amount`, `confirmations`) bulunur

- Depozito id'leri `dep_` ile başlar; `amount` ABD senti, `amount_token` coin tutarıdır ve fiyatlanan coin'lerde kullanılan `rate` da yer alır

Minimumun altındaki transferler (genellikle $1, BTC $5) `below_min` olarak kaydedilir ve otomatik yatırılmaz; yatırılması için bize ulaşın.

### Webhook'lar

Panelde (“Geliştiriciler › Entegrasyon ve anahtarlar”; Live ve Test'in her birinin kendi URL'si ve secret'ı vardır) tanımlı webhook URL'sine JSON POST'larız. Gövde olayın kendisidir:

```http
POST /your/webhook
X-BW-Event: ev_01J8…
X-BW-Delivery: 1
X-BW-Signature: t=1793693052,v1=5f0c9b…

{"id":"ev_01J8…","type":"invoice.paid","created_at":"2026-11-03T08:04:12.000Z","invoice":{"id":"inv_01J8…","ref":"order_1042","status":"paid","amount":4200,…}}
```

- `X-BW-Signature`: `t=<unix seconds>,v1=<hex>`; burada `v1` = HMAC-SHA256(o modun webhook secret'ı, `t` + `.` + ham gövde)

- `X-BW-Event`: olay id'si (`ev_…`); tekrarları buna göre ayıklayın

- `X-BW-Delivery`: deneme numarası, 1'den başlar

| Olay | Ne zaman |
| --- | --- |
| `invoice.paid` | Fatura `paid` veya `paid_over` oldu (süre dolduktan sonra gelen para dahil) |
| `invoice.wrong_amount` | Fatura `wrong_amount` olarak bitti |
| `invoice.closed` | Fatura hiçbir şey gelmeden süresi dolarak bitti ya da siz kapattınız |
| `deposit.credited` | Bir deposit hesabına gelen transfer yatırıldı |

Ayrıştırmadan önce ham gövde üzerinden doğrulayın, saatinizden 300 saniyeden fazla sapan bir `t` değerini reddedin ve karşılaştırmayı sabit sürede yapın. Gövdedeki `invoice` / `deposit`, bir sorgunun döndürdüğü nesnenin aynısıdır.

```nodejs
import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), header: X-BW-Signature
function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return typeof parts.v1 === "string" && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}
```

2xx yanıt teslim edildi sayılır; aksi halde 1 dakika, 5 dakika, 30 dakika, 2 saat, 12 saat, 24 saat ve 24 saat sonra yeniden deneriz (toplam 8 deneme).

### Events ve yeniden gönderim

`GET /v1/events?invoice_id=inv_…` (veya `deposit_id=dep_…`) bir fatura ya da depozitonun webhook'larını `state`, `attempts`, `last_status` ve `last_error` ile listeler. `POST /v1/events/ev_…/redeliver` onu hemen yeniden kuyruğa alır; örneğin endpoint'inizi düzelttikten sonra. Panelin “Geliştiriciler › Webhook günlüğü” sayfası her denemeyi istek ve yanıtıyla gösterir.

### Test modu

`bw_test_` anahtarıyla oluşturulan faturalar testnet'lerde çalışır ve gerçek paraya hiç dokunmaz. Ödeme sayfasında bir “Ödemeyi simüle et” düğmesi (tam / yarım / fazla ödeme) bulunur; böylece testnet coin'i olmadan durumları ve webhook'ları izleyebilirsiniz.
