सामग्री पर जाएँ
दस्तावेज़
इस पृष्ठ पर

इंटीग्रेशन गाइड

डेवलपर डॉक्यूमेंटेशन

इनवॉइस बनाएँ, ग्राहक को भुगतान पृष्ठ पर भेजें, और भुगतान होने पर हस्ताक्षरित वेबहुक पाएँ। नीचे दिए चार चरणों से शुरू करें।

  1. अपने प्रोजेक्ट की API कुंजी कॉपी करें।
  2. राइट अनुरोधों पर हस्ताक्षर करें।
  3. अपना पहला इनवॉइस बनाएँ।
  4. भुगतान वेबहुक को सत्यापित करें।

क्या समर्थित है

गेटवे USDT और USDC स्वीकार करता है। यह तालिका GET /v1/services से मेल खाती है, जिसे 4 नवंबर 2026 को जाँचा गया। भुगतान का तरीका चुनने वाला अपना पिकर बनाने से पहले मौजूदा कैटलॉग देखें।

एसेटनेटवर्ककन्फ़र्मेशन
USDTTron20
USDTEthereum12
USDTSolana32
USDTPolygon8
USDTArbitrum12
USDTTON5
USDCEthereum12
USDCSolana32
USDCPolygon8
USDCBase12
USDCArbitrum12

भुगतान कस्टोडियल हैं: राशि प्लेटफ़ॉर्म के नियंत्रण वाले पतों पर आती है। आपका व्यापारी बैलेंस वह राशि है जो आपको देय है। अलग Telegram वॉलेट नॉन-कस्टोडियल है।

सीमाएँ

  • पेआउट और रिफ़ंड अभी लाइव नहीं हैं: GET /v1/services में boundaries.livePayouts और boundaries.liveRefunds का मान false है।
  • आने वाले भुगतानों की जाँच किसी KYT प्रदाता द्वारा नहीं की जाती।
  • जिन इनवॉइस पर शुल्क राशि के 20% से ज़्यादा हो जाए, वे AMOUNT_BELOW_MINIMUM के साथ अस्वीकार कर दिए जाते हैं।
  • कोई अनुबंधित SLA नहीं।

शुरुआती शुल्क 0.40% और साथ में नेटवर्क शुल्क है। कुल शुल्क और न्यूनतम राशि जानने के लिए शुल्क कोटेशन का अनुरोध करें; कीमतें देखें।

ऑथेंटिकेशन

सर्वर-से-सर्वर कॉल x-api-key का उपयोग करते हैं। प्रोजेक्ट कुंजियाँ एक ही व्यापारी प्रोजेक्ट तक सीमित होती हैं। इन्हें अपने सर्वर पर ही रखें।

टेस्ट कुंजियाँ ncp_test_… से शुरू होती हैं; लाइव कुंजियाँ ncp_live_… से। पहले जारी की गई कुंजियाँ ncp_sandbox_ से शुरू होती हैं; वे काम करती रहेंगी।

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

राइट अनुरोधों पर हस्ताक्षर करें

GET अनुरोधों के लिए केवल x-api-key चाहिए। प्रोजेक्ट कुंजी से ऑथेंटिकेट किए गए हर POST, PUT, PATCH और DELETE अनुरोध के लिए दो और हेडर भी चाहिए, वरना API 401 Invalid API signature लौटाता है:

  • x-ncp-timestamp: ISO-8601 फ़ॉर्मैट में, मौजूदा समय से 5 मिनट के भीतर।
  • x-ncp-signature: hex(HMAC-SHA256(your API key, "<timestamp>.<METHOD>.<path incl. query>.<raw body>"))।

मेथड बड़े अक्षरों (uppercase) में लिखें। ठीक वही बाइट्स साइन करें जो आप भेजते हैं, पाथ में मौजूद क्वेरी स्ट्रिंग सहित। बिना बॉडी वाला अनुरोध खाली स्ट्रिंग साइन करता है। नीचे दिए हेल्पर के लिए आपकी प्रोजेक्ट कुंजी चाहिए; शेल हेल्पर के लिए Bash, curl और OpenSSL चाहिए, और Node.js हेल्पर नेटिव fetch का उपयोग करता है।

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
}

अपना पहला इनवॉइस बनाएँ

डैशबोर्ड में प्रोजेक्ट बनाएँ, उसकी API कुंजी कॉपी करें और इनवॉइस बनाएँ। रिस्पॉन्स में checkoutUrl होता है: अपने ग्राहक को वहाँ भेजें।

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

रिस्पॉन्स का अंश। ID हर इनवॉइस के लिए अलग से जनरेट होती है।

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

amountMinor मुद्रा की सबसे छोटी इकाई में पूर्णांक स्ट्रिंग है: 10000 = 100.00 USD। दशमलव amount फ़ील्ड केवल ब्राउज़र एंडपॉइंट /v1/public/payments स्वीकार करता है।

ब्राउज़र से भुगतान और अनुमत ऑरिजिन

डैशबोर्ड में पब्लिशेबल कुंजी बनाएँ और वे सटीक ऑरिजिन दर्ज करें जिनका आपका स्टोरफ़्रंट उपयोग करता है। ब्राउज़र अनुरोध इसे x-publishable-key के रूप में POST /v1/public/payments पर भेजते हैं।

Origin, successUrl और cancelUrl तीनों कुंजी की अनुमत ऑरिजिन सूची में होने चाहिए। ऑरिजिन का मतलब है स्कीम, होस्ट और वैकल्पिक पोर्ट, बिना पाथ या वाइल्डकार्ड के। गायब या सूची से बाहर के ऑरिजिन अस्वीकार कर दिए जाते हैं।

दशमलव राशि में फ़िएट के लिए दशमलव के बाद अधिकतम दो अंक, और क्रिप्टो के लिए एसेट के अपने दशमलव स्थानों तक अंक स्वीकार किए जाते हैं (USDT और USDC: आज हमारे हर समर्थित नेटवर्क पर 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);

भुगतान के स्टेटस

स्टेटसअगला कदम
newभुगतान पृष्ठ का लिंक साझा करें
pendingभुगतान की प्रतीक्षा
confirmingकन्फ़र्मेशन की प्रतीक्षा
paidसेटलमेंट के लिए तैयार
partially_paidग्राहक से भुगतान पूरा करने को कहें
overpaidक्रेडिट की गई अतिरिक्त राशि की समीक्षा करें
expiredनया इनवॉइस बनाएँ
cancelledकोई कार्रवाई ज़रूरी नहीं
failedविवरण खोलें
refundedकोई कार्रवाई ज़रूरी नहीं

Idempotency कुंजियाँ

इनवॉइस बनाते समय अपने ऑर्डर ID से बनी एक स्थिर Idempotency-Key भेजें। उसी कुंजी और बॉडी के साथ दोबारा कोशिश करने पर मूल इनवॉइस लौटता है। अलग बॉडी के साथ इसे दोबारा इस्तेमाल करने पर 409 लौटता है। टाइमआउट के बाद दोबारा कोशिश करते समय कुंजी और बॉडी में कोई बदलाव न करें।

अनुरोध के लिए पहले इनवॉइस का उदाहरण देखें।

त्रुटियाँ

त्रुटियाँ JSON में होती हैं। message एक स्ट्रिंग है, या वैलिडेशन त्रुटियों के लिए स्ट्रिंग्स की एक ऐरे।

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid API key"
}
HTTP स्टेटसअर्थ और कार्रवाई
400अमान्य फ़ील्ड; message में फ़ील्ड का नाम होता है। दोबारा कोशिश करने से पहले इसे ठीक करें।
401Invalid API key या Invalid API signature। कुंजी, साइन की गई बाइट्स और टाइमस्टैम्प जाँचें।
404Payment invoice not found। ID और प्रोजेक्ट जाँचें।
409वही Idempotency-Key अलग बॉडी के साथ, या Insufficient merchant payable balance।
429रेट लिमिट लागू है। दोबारा कोशिश करने से पहले प्रतीक्षा करें।
5xxउसी Idempotency-Key और बॉडी के साथ दोबारा कोशिश करें।

वेबहुक (HMAC-SHA256)

हर डिलीवरी में x-nebula-signature: t=<unix>,v1=<hex> होता है। एंडपॉइंट बनाते समय लौटाए गए एंडपॉइंट सीक्रेट से HMAC सत्यापित करें। मौजूदा समय से 300 सेकंड से ज़्यादा अंतर वाले टाइमस्टैम्प अस्वीकार करें।

Node.js में सत्यापन

Node.js वेरिफ़ायर केवल बिल्ट-इन crypto मॉड्यूल का उपयोग करता है। इसमें सिग्नेचर हेडर, रॉ बॉडी बाइट्स और एंडपॉइंट सीक्रेट पास करें।

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));
}

JSON पार्स करने से पहले, रॉ अनुरोध बॉडी के आधार पर सत्यापन करें। डिलीवरी कम से कम एक बार होती है: x-nebula-event-id के आधार पर डुप्लिकेट हटाएँ, जो पेलोड के eventId से मेल खाता है। स्वचालित रीट्राई में डिलीवरी ID वही रहती है; मैन्युअल रूप से दोबारा भेजने पर उसी इवेंट ID के साथ नई डिलीवरी ID बनती है। 2xx जवाब देने से पहले इवेंट को सहेज लें।

लोकल रूप से वेबहुक का परीक्षण

वेबहुक URL में सार्वजनिक इंटरनेट होस्ट होना चाहिए। लोकल और निजी पते अस्वीकार कर दिए जाते हैं। अपने रिसीवर को सार्वजनिक HTTPS टनल के ज़रिए उपलब्ध कराएँ, फिर साइनिंग हेल्पर से उसका URL रजिस्टर करें।

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

URL की जगह अपने रिसीवर का URL डालें। बनाते समय लौटाया गया एंडपॉइंट सीक्रेट सहेज लें।

इवेंट के प्रकार

पेआउट और रिफ़ंड अभी लाइव नहीं हैं (GET /v1/services में boundaries.livePayouts का मान false है)। तब तक पेआउट और पेआउट बैच केवल आपके बैलेंस में ट्रांसफ़र दर्ज करते हैं; payout.completed और refund.completed का मतलब यह नहीं है कि राशि बाहर भेजी गई।

नीचे दिया कैटलॉग GET /v1/services से मेल खाता है। कैटलॉग में किसी एंट्री का मतलब यह नहीं है कि उससे जुड़ा धन का लेन-देन लाइव है।

इवेंटअर्थ
webhook.testकिसी वेबहुक एंडपॉइंट के लिए अनुरोधित टेस्ट डिलीवरी।
payment.pendingग्राहक ने भुगतान का तरीका चुन लिया है; पहली जमा राशि की प्रतीक्षा है।
payment.confirmingजमा राशि दिखी है; ज़रूरी कन्फ़र्मेशन की प्रतीक्षा है।
payment.paidइनवॉइस का पूरा भुगतान हो गया और लेजर में सेटल हो गया।
payment.partially_paidमाँगी गई राशि से कम मिली; बाकी राशि की प्रतीक्षा है।
payment.overpaidमाँगी गई राशि से ज़्यादा मिली; अतिरिक्त भुगतान सहित लेजर में सेटल हो गया।
payment.expiredपर्याप्त राशि के बिना इनवॉइस की अवधि समाप्त हो गई।
payment.cancelledभुगतान से पहले इनवॉइस रद्द कर दिया गया।
payment.failedचेन, शुल्क नीति या ऑब्ज़र्वेशन से जुड़ी त्रुटि के कारण भुगतान विफल रहा।
payment.risk_flaggedपहले से क्रेडिट की गई जमा राशि के लिए सलाहकारी जोखिम इवेंट। आने वाले भुगतानों की KYT जाँच लाइव नहीं है।
payment.reorgedचेन रीऑर्गनाइज़ेशन के कारण एक कन्फ़र्म जमा राशि हट गई; इनवॉइस अब भुगतान किया हुआ नहीं है, इसलिए ऑर्डर पूरा करना रोकें या उसे वापस लें।
payment.unsupported_assetएक असमर्थित टोकन जमा किया गया; उसे क्रेडिट नहीं किया गया।
payout.processingपेआउट प्रोसेसिंग की स्थिति। लाइव ट्रांसफ़र उपलब्ध नहीं हैं।
payout.completedपेआउट बैलेंस में दर्ज हुआ; इसका मतलब यह नहीं है कि राशि बाहर भेजी गई।
payout.failedपेआउट विफल रहा।
payout.cancelledपेआउट पूरा होने से पहले रद्द कर दिया गया।
refund.processingरिफ़ंड प्रोसेसिंग की स्थिति। लाइव रिफ़ंड उपलब्ध नहीं हैं।
refund.completedरिफ़ंड बैलेंस में दर्ज हुआ; इसका मतलब यह नहीं है कि राशि बाहर भेजी गई।
refund.failedरिफ़ंड विफल रहा।
internal_transfer.sentएक व्यापारी से दूसरे व्यापारी को बैलेंस ट्रांसफ़र भेजने वाले के लिए दर्ज हुआ।
internal_transfer.receivedएक व्यापारी से दूसरे व्यापारी को बैलेंस ट्रांसफ़र प्राप्तकर्ता के खाते में क्रेडिट हुआ।
static_wallet.createdकिसी ग्राहक के लिए लंबे समय तक चलने वाला जमा पता बनाया गया।
static_wallet.blockedएक स्टैटिक वॉलेट ब्लॉक किया गया।
static_wallet.unblockedएक स्टैटिक वॉलेट से ब्लॉक हटाया गया।
static_wallet.topup.completedस्टैटिक वॉलेट में जमा राशि दिखी और लेजर में सेटल हो गई।
dispute.openedकिसी इनवॉइस पर विवाद खोला गया।
dispute.resolvedविवाद सुलझा लिया गया। केवल समाधान से यह साबित नहीं होता कि ऑन-चेन रिफ़ंड हुआ है।
dispute.rejectedविवाद अस्वीकार कर दिया गया; व्यापारी को कोई कार्रवाई नहीं करनी है।
subscription.invoice_createdएक बिलिंग साइकिल ने नया इनवॉइस बनाया।

रीट्राई नीति

अगर आपका एंडपॉइंट 2xx जवाब नहीं देता, तो हम कुल 8 बार कोशिश करते हैं: पहली कोशिश, फिर 1 मिनट, 5 मिनट, 30 मिनट, 2 घंटे, 6 घंटे, 12 घंटे और 24 घंटे बाद रीट्राई। हर अंतराल पिछली विफल कोशिश के बाद शुरू होता है। नेटवर्क त्रुटियाँ और टाइमआउट भी विफलता माने जाते हैं। टेस्ट डिलीवरी में केवल एक कोशिश होती है।

आख़िरी विफलता के बाद डिलीवरी को विफल चिह्नित कर दिया जाता है; इसे POST /v1/webhooks/deliveries/{deliveryId}/resend से दोबारा भेजें। बैकअप के तौर पर GET /v1/payments/{id} से मिलान करें।

पेआउट और रिफ़ंड अभी लाइव नहीं हैं (GET /v1/services में boundaries.livePayouts का मान false है)। तब तक पेआउट और पेआउट बैच केवल आपके बैलेंस में ट्रांसफ़र दर्ज करते हैं; payout.completed और refund.completed का मतलब यह नहीं है कि राशि बाहर भेजी गई।

पेआउट बैच

एक बैच ट्रांसफ़र रिकॉर्ड को समूह में रखता है। इसकी अनुमोदन नीति और ज़रूरी अनुमोदनों की संख्या approvalPolicy और approvalsRequired के रूप में लौटाई जाती है। एक से ज़्यादा अनुमोदक होने पर, बैच बनाने वाला अपना बैच अनुमोदित नहीं कर सकता। अगर केवल एक ही योग्य ऑपरेटर है, तो वह अपने सेशन में बनाया गया बैच खुद अनुमोदित कर सकता है। डैशबोर्ड में WebAuthn से बैच अनुमोदित करें।

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"

गंतव्य की जगह अपने टेस्ट प्रोजेक्ट का कोई मान्य पता डालें।

आवर्ती बिलिंग

सब्सक्रिप्शन हर बिलिंग साइकिल में एक नया इनवॉइस बनाता है और subscription.invoice_created के ज़रिए इसकी सूचना देता है। यह ग्राहक के वॉलेट से अपने-आप राशि नहीं काटता। ग्राहक को भुगतान पृष्ठ का नया URL भेजें।

interval: DAY, WEEK, MONTH या YEAR।

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

API संदर्भ में दिए लाइफ़साइकिल ऑपरेशनों से रोकें, फिर से शुरू करें या रद्द करें।

जोखिम जाँच

पेआउट और रिफ़ंड के गंतव्यों को ट्रांसफ़र बनाए जाने से पहले सार्वजनिक प्रतिबंध सूचियों से जाँचा जाता है; मेल मिलने पर अनुरोध अस्वीकार कर दिया जाता है। आने वाले भुगतानों की जाँच नहीं की जाती।

AML और प्रतिबंध नीति

व्यापारियों के लिए Telegram बॉट

@veilnebula_bot एक समय में एक ही प्रोजेक्ट के साथ काम करता है। उस प्रोजेक्ट की API कुंजी से इसे निजी चैट में लिंक करें। बॉट आपका संदेश हटाने की कोशिश करता है और सहेजी गई कुंजी को एन्क्रिप्ट करता है। अगर संदेश नहीं हटता, तो कुंजी रद्द करें और नई कुंजी बनाएँ। किसी साझा चैट में कभी भी कुंजी पोस्ट न करें।

सूचनाएँ लिंक किए गए प्रोजेक्ट और सक्रिय कुंजी तक सीमित रहती हैं। पेआउट अनुमोदित करने के लिए डैशबोर्ड खोलें।

/link <API_KEY>
/balance
/invoices
/notify on
/unlink
इंटीग्रेशन गाइड · VeilNebula