डेवलपर दस्तावेज़
Kem Business API से USDT भुगतान लेने के लिए जो कुछ चाहिए: प्रमाणीकरण, भुगतान endpoints, और हस्ताक्षरित webhooks जो आपके ऑर्डर की स्थिति चलाते हैं।
प्रमाणीकरण
डैशबोर्ड में «API keys» से कुंजियाँ बनाएँ और हर अनुरोध में secret key को Bearer token के रूप में भेजें। टेस्ट कुंजियाँ (sk_test_…) टेस्ट भुगतान बनाती हैं; लाइव कुंजियाँ (sk_live_…) असली पैसा चलाती हैं।
Authorization: Bearer sk_live_... # or sk_test_...
Base URL: https://api-business.kemapp.ioभुगतान
भुगतान बनाएँ और ग्राहक को उसके होस्टेड checkout_url पर भेजें — वॉलेट, नेटवर्क और पुष्टि Kem संभालती है। स्थिति भुगतान fetch करके या बेहतर, webhooks से ट्रैक करें।
/v1/paymentscurl -X POST https://api-business.kemapp.io/v1/payments \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{
"amount": "25.000000",
"currency": "USDT",
"merchant_reference": "order-1042",
"customer_email": "[email protected]",
"description": "Pro plan",
"return_url": "https://yourshop.example/thanks",
"metadata": {"order_id": "1042"}
}'{
"id": "pay_01J...",
"status": "pending",
"mode": "test",
"amount": "25.000000",
"amount_minor": 25000000,
"amount_refunded_minor": 0,
"fee_bps": null,
"fee_minor": null,
"net_minor": null,
"currency": "USDT",
"network": null,
"merchant_reference": "order-1042",
"checkout_url": "https://pay.kemapp.io/pay_01J...",
"checkout_expires_at": "2026-07-13T13:30:00+00:00",
"transaction_id": null,
"detected_at": null,
"confirmation_pending": false,
"created_at": "2026-07-13T13:00:00+00:00",
"updated_at": "2026-07-13T13:00:00+00:00"
}Idempotency-Key — वैकल्पिक पर अनुशंसित — उसी key से दोबारा प्रयास करने पर डुप्लिकेट के बजाय मूल भुगतान लौटता है।
/v1/payments— query: status, limit (1–100, default 20), cursor · returns has_more, next_cursor/v1/payments/{id}amount — decimal string with 6 places ("25.000000"); amount_minor — the same value as an integer in micro-USDT.
fee_minor and net_minor are null while a payment is in flight and are frozen when it succeeds. Reconcile your payout against net_minor, not amount_minor — the difference is our fee (fee_bps).
भुगतान जीवनचक्र
pending → detected → succeeded · failed · expired
pending — ट्रांसफ़र की प्रतीक्षा · detected — चेन पर दिखा, पुष्टि हो रही है · succeeded — धन आपके वॉलेट में पक्का (इसी पर ऑर्डर पूरा करें) · failed / expired — अंतिम। रिफ़ंड बदलाव webhook इवेंट से आते हैं।
checkout window: 30 minutes, then → expired
त्रुटियाँ और सीमाएँ
हर त्रुटि एक ही envelope में आती है। कोड स्थिर हैं — संदेश पर नहीं, error.code पर शाखा करें।
HTTP 4xx/5xx
{
"error": {
"code": "idempotency_conflict",
"message": "Idempotency-Key reused with a different request"
}
}| 401 unauthorized | missing or invalid API key |
| 404 payment_not_found | unknown payment id (or a live id with a test key) |
| 409 idempotency_conflict | Idempotency-Key reused with a different body — identical retries replay the original response |
| 422 validation_error | malformed body — bad amount, unsupported currency. message reads “{field}: {reason}” |
| 429 rate_limited | over the per-key budget: 100 writes/min, 1000 reads/min |
उत्पाद, भुगतान लिंक, webhook endpoints और रिफ़ंड डैशबोर्ड से प्रबंधित होते हैं — इनके सार्वजनिक REST endpoints अभी नहीं हैं।
Webhooks
डैशबोर्ड में «Webhooks» से endpoint जोड़ें और ज़रूरी इवेंट चुनें। हर endpoint को अपना whsec_… signing secret मिलता है, जो बनाते समय एक बार दिखता है।
| payment.created | A payment intent was created (API or checkout link). |
| payment.detected | The transfer was seen on-chain / in the KEM ledger; confirming. |
| payment.succeeded | Funds are confirmed in your business wallet. Fulfill on this event. |
| payment.failed | The payment failed. |
| payment.expired | The checkout window closed without payment. |
| payment.confirmation_delayed | The customer paid, but it couldn't be confirmed inside the checkout window. Don't treat this as expired — hold the order. |
| payment.refund.created | A refund was initiated from the dashboard. |
| payment.refund.succeeded | The refund settled back to the customer. |
इवेंट पेलोड
{
"id": "payment_event_01J...",
"type": "payment.succeeded",
"created": "2026-07-13T13:04:12+00:00",
"data": {
"payment": {
"id": "pay_01J...",
"status": "succeeded",
"amount_minor": 25000000,
"currency": "USDT",
"merchant_reference": "order-1042",
"network": "TRON",
"product_id": null,
"payment_link_id": null
}
}
}हस्ताक्षर सत्यापन
हर डिलीवरी में Kem-Signature हेडर होता है। अपने endpoint secret से «<t>.» + कच्चे बॉडी पर HMAC दोबारा निकालें और constant-time तुलना करें। मेल न खाने पर अस्वीकार करें।
Kem-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>
signed_input = "<t>." + raw_request_body
v1 = HMAC_SHA256(endpoint_secret, signed_input) # secret: whsec_...
# reject replays: drop the delivery when |now - t| > 300simport crypto from "node:crypto";
export function verifyKemSignature(rawBody, header, secret) {
// header: "t=1720000000,v1=hex"
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto
.createHmac("sha256", secret) // secret: whsec_...
.update(`${parts.t}.`)
.update(rawBody) // the RAW request bytes
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}import hashlib, hmac
def verify_kem_signature(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=") for p in header.split(","))
expected = hmac.new(
secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, parts["v1"])डिलीवरी और पुनःप्रयास
जल्दी 2xx लौटाएँ। असफल डिलीवरी backoff से दोहराई जाती हैं, फिर dead-letter हो जाती हैं:
1m · 5m · 30m · 2h · 12h · 24h
परीक्षण
टेस्ट key से बिना पैसा चलाए भुगतान को पूरे जीवनचक्र से गुज़ारें — ट्रांज़िशन सिम्युलेट करें और अपने webhooks आते देखें:
curl -X POST https://api-business.kemapp.io/v1/payments/{id}/_simulate/succeeded \
-H "Authorization: Bearer sk_test_..."