İçeriğe geç
Belgeler
Bu sayfada

Entegrasyon kılavuzu

Geliştirici belgeleri

Bir fatura oluşturun, müşteriyi ödeme sayfasına yönlendirin, ödendiğinde imzalı bir webhook alın. Aşağıdaki dört adımla başlayın.

  1. Projenizin API anahtarını kopyalayın.
  2. Yazma isteklerini imzalayın.
  3. İlk faturanızı oluşturun.
  4. Ödeme webhook’unu doğrulayın.

Neler destekleniyor

Ödeme altyapısı USDT ve USDC kabul eder. Bu tablo, 4 Kasım 2026 tarihinde kontrol edilen GET /v1/services ile eşleşir. Ödeme yöntemi seçicinizi geliştirmeden önce güncel kataloğu okuyun.

VarlıkAğOnaylar
USDTTron20
USDTEthereum12
USDTSolana32
USDTPolygon8
USDTArbitrum12
USDTTON5
USDCEthereum12
USDCSolana32
USDCPolygon8
USDCBase12
USDCArbitrum12

Ödemeler gözetimlidir: fonlar platformun kontrol ettiği adreslere gelir. Satıcı bakiyeniz, size borçlu olunan tutardır. Ayrı bir ürün olan Telegram cüzdanı ise gözetimsizdir.

Sınırlamalar

  • Ödeme gönderimi ve iadeler henüz canlı değildir: GET /v1/services, boundaries.livePayouts ve boundaries.liveRefunds değerlerini false olarak bildirir.
  • Gelen ödemeler bir KYT sağlayıcısı tarafından taranmaz.
  • Ücretlerin tutarın %20’sini aşacağı faturalar AMOUNT_BELOW_MINIMUM ile reddedilir.
  • Sözleşmeye bağlı SLA yoktur.

Başlangıç ücreti %0,40 artı ağ ücretidir. Toplam ve minimum tutar için bir ücret teklifi isteyin; fiyatlandırmaya bakın.

Kimlik doğrulama

Sunucudan sunucuya çağrılar x-api-key kullanır. Proje anahtarları tek bir satıcı projesiyle sınırlıdır. Bunları sunucunuzda tutun.

Test anahtarları ncp_test_… ile, canlı mod anahtarları ncp_live_… ile başlar. Daha önce oluşturulan anahtarlar ncp_sandbox_ ile başlar ve çalışmaya devam eder.

curl -sS "https://api.veilnebu.la/v1/balances" \
  -H "x-api-key: $PROJECT_API_KEY"

Yazma isteklerini imzalayın

GET istekleri yalnızca x-api-key gerektirir. Bir proje anahtarıyla kimliği doğrulanan her POST, PUT, PATCH ve DELETE isteği ayrıca iki başlık gerektirir; aksi takdirde API 401 Invalid API signature yanıtını verir:

  • x-ncp-timestamp: ISO-8601, şu andan en fazla 5 dakika farklı.
  • x-ncp-signature: hex(HMAC-SHA256(your API key, "<timestamp>.<METHOD>.<path incl. query>.<raw body>")).

Metotları büyük harfle kullanın. Gönderdiğiniz baytları, yoldaki sorgu dizesi dahil, tam olarak imzalayın. Gövdesi olmayan bir istek boş bir dizeyi imzalar. Aşağıdaki yardımcılar proje anahtarınızı gerektirir; kabuk yardımcısı Bash, curl ve OpenSSL gerektirir, Node.js yardımcısı ise yerleşik fetch kullanır.

export API_BASE_URL="https://api.veilnebu.la"
export PROJECT_API_KEY="ncp_test_…"

ncp() {
  local method="$1" path="$2" body="" ts sig
  shift 2
  if [ "$#" -gt 0 ]; then body="$1"; shift; fi
  ts=$(date -u +%Y-%m-%dT%H:%M:%S.000Z) || return
  sig=$(printf '%s.%s.%s.%s' "$ts" "$method" "$path" "$body" |
    openssl dgst -sha256 -hmac "$PROJECT_API_KEY" -hex) || return
  sig=${sig##* }
  if [ -n "$body" ]; then
    curl -sS --request "$method" "$API_BASE_URL$path" \
      -H "x-api-key: $PROJECT_API_KEY" \
      -H "x-ncp-timestamp: $ts" -H "x-ncp-signature: $sig" \
      -H "content-type: application/json" --data-binary "$body" "$@"
  else
    curl -sS --request "$method" "$API_BASE_URL$path" \
      -H "x-api-key: $PROJECT_API_KEY" \
      -H "x-ncp-timestamp: $ts" -H "x-ncp-signature: $sig" "$@"
  fi
}

İlk faturanızı oluşturun

Panelde bir proje oluşturun, API anahtarını kopyalayın ve bir fatura oluşturun. Yanıt checkoutUrl içerir: müşterinizi oraya yönlendirin.

ncp POST /v1/payments '{
  "amountMinor":"10000",
  "currencyCode":"USD",
  "settlementAssetCode":"USDT",
  "externalId":"order-1001"
}' -H "idempotency-key: order-1001"

Yanıttan bir bölüm. Kimlik her fatura için ayrı oluşturulur.

{
  "id": "cm3k9x2f40001qz8e7h5v1abc",
  "status": "new",
  "amountMinor": "10000",
  "currencyCode": "USD",
  "settlementAssetCode": "USDT",
  "checkoutUrl": "https://app.veilnebu.la/checkout/cm3k9x2f40001qz8e7h5v1abc"
}

amountMinor, para biriminin en küçük birimindeki tam sayıyı içeren bir dizedir: 10000 = 100.00 USD. Ondalıklı amount alanı yalnızca tarayıcı uç noktası /v1/public/payments tarafından kabul edilir.

Tarayıcıdan ödeme sayfası ve izin verilen kaynaklar

Panelde yayımlanabilir bir anahtar oluşturun ve mağazanızın kullandığı kaynakları tam olarak listeleyin. Tarayıcı istekleri bu anahtarı x-publishable-key olarak POST /v1/public/payments adresine gönderir.

Kaynak, successUrl ve cancelUrl değerlerinin tümü anahtarın izin verilen kaynaklar listesinde olmalıdır. Kaynak; şema, ana bilgisayar ve isteğe bağlı bağlantı noktasından oluşur, yol veya joker karakter içermez. Eksik veya listede olmayan kaynaklar reddedilir.

Ondalıklı tutar, itibari para birimleri için en fazla iki ondalık basamak, kripto için ise varlığın kendi ondalık basamak sayısına kadar kabul eder (USDT ve USDC: bugün desteklediğimiz tüm ağlarda 6).

const response = await fetch('https://api.veilnebu.la/v1/public/payments', {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    'x-publishable-key': 'pk_test_…',
  },
  body: JSON.stringify({
    amount: '100.00',
    currencyCode: 'USD',
    settlementAssetCode: 'USDT',
    successUrl: 'https://shop.example/thanks',
    cancelUrl: 'https://shop.example/cart',
  }),
});
if (!response.ok) throw new Error(await response.text());
const invoice = await response.json();
window.location.assign(invoice.checkoutUrl);

Ödeme durumları

DurumSonraki işlem
newÖdeme sayfası bağlantısını paylaşın
pendingÖdeme bekleniyor
confirmingOnaylar bekleniyor
paidMutabakata hazır
partially_paidMüşteriden ödemeyi tamamlamasını isteyin
overpaidFazladan yatırılan tutarı inceleyin
expiredYeni bir fatura oluşturun
cancelledİşlem gerekmez
failedAyrıntıları açın
refundedİşlem gerekmez

Idempotency anahtarları

Fatura oluştururken, sipariş kimliğinizden türetilmiş sabit bir Idempotency-Key gönderin. Aynı anahtar ve gövdeyle yapılan yeniden deneme özgün faturayı döndürür. Anahtarı farklı bir gövdeyle yeniden kullanmak 409 döndürür. Zaman aşımından sonra yeniden denerken anahtarı ve gövdeyi değiştirmeyin.

İstek için ilk fatura örneğine bakın.

Hatalar

Hatalar JSON biçimindedir. message bir dizedir; doğrulama hatalarında ise dizelerden oluşan bir dizidir.

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid API key"
}
HTTP durumuAnlamı ve yapılacak işlem
400Geçersiz alan; "message" alanın adını belirtir. Yeniden denemeden önce düzeltin.
401"Invalid API key" veya "Invalid API signature". Anahtarı, imzalanan baytları ve zaman damgasını kontrol edin.
404"Payment invoice not found". Kimliği ve projeyi kontrol edin.
409Farklı bir gövdeyle aynı "Idempotency-Key" veya "Insufficient merchant payable balance".
429İstek sınırına ulaşıldı. Yeniden denemeden önce bekleyin.
5xxAynı "Idempotency-Key" ve gövdeyle yeniden deneyin.

Webhook’lar (HMAC-SHA256)

Her teslimat x-nebula-signature: t=<unix>,v1=<hex> taşır. HMAC’i, uç noktayı oluşturduğunuzda döndürülen uç nokta sırrıyla doğrulayın. Şu andan 300 saniyeden fazla farklı olan zaman damgalarını reddedin.

Node.js ile doğrulama

Node.js doğrulayıcısı yalnızca yerleşik crypto modülünü kullanır. İmza başlığını, ham gövde baytlarını ve uç nokta sırrını ona iletin.

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(header, rawBody, secret) {
  const parts = {};
  for (const piece of (header ?? '').split(',')) {
    const separator = piece.indexOf('=');
    if (separator <= 0) continue;
    parts[piece.slice(0, separator).trim()] = piece.slice(separator + 1).trim();
  }
  if (!/^[0-9]{1,16}$/.test(parts.t ?? '')) return false;
  if (!/^[0-9a-f]{64}$/.test(parts.v1 ?? '')) return false;
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac('sha256', secret)
    .update(parts.t + '.')
    .update(rawBody)
    .digest('hex');
  if (expected.length !== parts.v1.length) return false;
  return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Doğrulamayı JSON ayrıştırmasından önce, ham istek gövdesi üzerinden yapın. Teslimat en az bir kez garantilidir: yükteki eventId ile eşleşen x-nebula-event-id değerine göre yinelenenleri ayıklayın. Otomatik yeniden denemeler teslimat kimliğini korur; elle yeniden gönderim, aynı olay kimliğiyle yeni bir teslimat kimliği oluşturur. 2xx yanıtı vermeden önce olayı kalıcı olarak kaydedin.

Webhook’ları yerelde test etme

Webhook URL’leri herkese açık bir internet ana bilgisayarı kullanmalıdır. Yerel ve özel adresler reddedilir. Alıcınızı herkese açık bir HTTPS tüneliyle dışarı açın, ardından URL’sini imzalama yardımcısıyla kaydedin.

ncp POST /v1/webhooks/endpoints '{
  "url":"https://receiver.example/webhook",
  "events":["payment.paid","payment.reorged"]
}'

URL’yi kendi alıcınızın adresiyle değiştirin. Oluşturma sırasında döndürülen uç nokta sırrını kaydedin.

Olay türleri

Ödeme gönderimi ve iadeler henüz canlı değildir (GET /v1/services, boundaries.livePayouts değerini false olarak bildirir). O zamana kadar ödeme gönderimleri ve ödeme gönderimi grupları transferi yalnızca bakiyenize kaydeder; payout.completed ve refund.completed, fonların çıktığı anlamına gelmez.

Aşağıdaki katalog GET /v1/services ile eşleşir. Katalogda bir kaydın bulunması, ilgili para hareketinin canlı olduğu anlamına gelmez.

OlayAnlamı
webhook.testBir webhook uç noktası için istenen test teslimatı.
payment.pendingMüşteri bir ödeme yöntemi seçti; ilk yatırma bekleniyor.
payment.confirmingYatırma görüldü; gerekli onaylar bekleniyor.
payment.paidFatura tamamen ödendi ve deftere işlendi.
payment.partially_paidİstenenden az tutar alındı; kalanı bekleniyor.
payment.overpaidİstenenden fazla tutar alındı; fazla ödemeyle birlikte deftere işlendi.
payment.expiredFaturanın süresi, yeterli fon gelmeden doldu.
payment.cancelledFatura, ödeme yapılmadan önce iptal edildi.
payment.failedÖdeme bir zincir, ücret politikası veya gözlem hatası nedeniyle başarısız oldu.
payment.risk_flaggedZaten hesaba geçirilmiş bir yatırma için bilgilendirme amaçlı risk olayı. Gelen ödemeler için KYT taraması canlı değildir.
payment.reorgedOnaylanmış bir yatırma, zincir yeniden düzenlenmesi nedeniyle düştü; fatura artık ödenmiş değildir, bu yüzden siparişin teslimini durdurun veya geri alın.
payment.unsupported_assetDesteklenmeyen bir token yatırıldı; hesaba geçirilmedi.
payout.processingÖdeme gönderiminin işlenme durumu. Canlı transferler açık değildir.
payout.completedÖdeme gönderimi bakiyeye kaydedildi; bu, fonların çıktığı anlamına gelmez.
payout.failedÖdeme gönderimi başarısız oldu.
payout.cancelledÖdeme gönderimi tamamlanmadan önce iptal edildi.
refund.processingİadenin işlenme durumu. Canlı iadeler açık değildir.
refund.completedİade bakiyeye kaydedildi; bu, fonların çıktığı anlamına gelmez.
refund.failedİade başarısız oldu.
internal_transfer.sentSatıcıdan satıcıya bakiye transferi gönderen için gerçekleştirildi.
internal_transfer.receivedSatıcıdan satıcıya bakiye transferi alıcının hesabına geçirildi.
static_wallet.createdBir müşteri için uzun ömürlü bir yatırma adresi oluşturuldu.
static_wallet.blockedBir statik cüzdan engellendi.
static_wallet.unblockedBir statik cüzdanın engeli kaldırıldı.
static_wallet.topup.completedStatik cüzdana bir yatırma görüldü ve deftere işlendi.
dispute.openedBir fatura için itiraz açıldı.
dispute.resolvedBir itiraz çözüldü. Çözüm tek başına zincir üzerinde bir iadeyi kanıtlamaz.
dispute.rejectedBir itiraz reddedildi; satıcının bir işlem yapması gerekmez.
subscription.invoice_createdBir faturalandırma dönemi yeni bir fatura oluşturdu.

Yeniden deneme politikası

Uç noktanız 2xx ile yanıt vermezse toplam 8 kez deneriz: ilk deneme, ardından 1 dakika, 5 dakika, 30 dakika, 2 saat, 6 saat, 12 saat ve 24 saat sonra yeniden denemeler. Her bekleme süresi önceki başarısız denemeden sonra başlar. Ağ hataları ve zaman aşımları da başarısızlık sayılır. Test teslimatlarında tek deneme yapılır.

Son başarısızlıktan sonra teslimat başarısız olarak işaretlenir; POST /v1/webhooks/deliveries/{deliveryId}/resend ile yeniden gönderin. Yedek yöntem olarak GET /v1/payments/{id} ile mutabakat yapın.

Ödeme gönderimi ve iadeler henüz canlı değildir (GET /v1/services, boundaries.livePayouts değerini false olarak bildirir). O zamana kadar ödeme gönderimleri ve ödeme gönderimi grupları transferi yalnızca bakiyenize kaydeder; payout.completed ve refund.completed, fonların çıktığı anlamına gelmez.

Ödeme gönderimi grupları

Bir grup, transfer kayıtlarını bir araya toplar. Grubun onay politikası ve gereken onay sayısı approvalPolicy ve approvalsRequired olarak döndürülür. Birden fazla onaylayıcı varsa, grubu oluşturan kişi kendi grubunu onaylayamaz. Yetkili tek operatör, oturumda kendi oluşturduğu grubu onaylayabilir. Grupları panelde WebAuthn ile onaylayın.

export PROJECT_API_KEY="ncp_test_…"
ncp POST /v1/payout-batches '{
  "assetCode":"USDT",
  "networkCode":"TRON",
  "externalId":"batch-1001",
  "items":[{
    "destinationAddress":"T…",
    "amountMinor":"15000000",
    "externalRef":"recipient-1001"
  }]
}' -H "idempotency-key: batch-1001"

Hedefi, kendi test projenizdeki geçerli bir adresle değiştirin.

Yinelenen faturalandırma

Bir abonelik her faturalandırma döneminde yeni bir fatura oluşturur ve bunu subscription.invoice_created ile bildirir. Müşterinin cüzdanından otomatik olarak ödeme çekmez. Müşteriye yeni ödeme sayfası URL’sini gönderin.

interval: DAY, WEEK, MONTH veya YEAR.

ncp POST /v1/subscriptions '{
  "customerRef":"customer-42",
  "assetCode":"USDT",
  "networkCode":"TRON",
  "amountMinor":"9000000",
  "interval":"MONTH",
  "intervalCount":1
}'

API referansındaki yaşam döngüsü işlemlerini kullanarak duraklatın, sürdürün veya iptal edin.

Risk taraması

Ödeme gönderimi ve iade hedefleri, transfer oluşturulmadan önce herkese açık yaptırım listeleriyle karşılaştırılır; bir eşleşme isteği reddeder. Gelen ödemeler taranmaz.

AML ve yaptırımlar politikası

Telegram satıcı botu

@veilnebula_bot aynı anda tek bir projeyle çalışır. Botu, o projenin API anahtarıyla özel bir sohbette bağlayın. Bot mesajınızı silmeye çalışır ve saklanan anahtarı şifreler. Silme başarısız olursa anahtarı iptal edip yenisini oluşturun. Bir anahtarı asla ortak bir sohbete göndermeyin.

Bildirimler, bağlı proje ve etkin anahtarla sınırlıdır. Ödeme gönderimlerini onaylamak için paneli açın.

/link <API_KEY>
/balance
/invoices
/notify on
/unlink
Entegrasyon kılavuzu · VeilNebula