kemBusiness
플랫폼제품작동 방식급여 지급개발자자주 묻는 질문
로그인시작하기↗

개발자 문서

Kem Business API로 USDT 결제를 받기 위해 필요한 모든 것: 인증, 결제 엔드포인트, 그리고 주문 상태를 이끄는 서명된 웹훅.

인증결제오류와 한도웹훅테스트

인증

대시보드의 「API 키」에서 키를 만들고, 모든 요청에 시크릿 키를 Bearer token으로 보내세요. 테스트 키(sk_test_…)는 테스트 결제를 만들고, 라이브 키(sk_live_…)는 실제 돈을 움직입니다.

Authorization: Bearer sk_live_...   # or sk_test_...
Base URL: https://api-business.kemapp.io

결제

결제를 생성하고 고객을 호스팅된 checkout_url로 보내세요 — 지갑·네트워크·확인은 Kem이 처리합니다. 결제를 조회하거나, 더 좋게는 웹훅으로 상태를 추적하세요.

POST/v1/payments
curl -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,
  "currency": "USDT",
  "merchant_reference": "order-1042",
  "checkout_url": "https://pay.kemapp.io/pay_01J...",
  "checkout_expires_at": "2026-07-13T13:30:00+00:00",
  "created_at": "2026-07-13T13:00:00+00:00"
}

Idempotency-Key — 선택이지만 권장 — 같은 키로 재시도하면 중복 생성 대신 원래 결제가 반환됩니다.

GET/v1/payments— query: status, limit (1–100, default 20), cursor · returns has_more, next_cursor
GET/v1/payments/{id}

amount — decimal string with 6 places ("25.000000"); amount_minor — the same value as an integer in micro-USDT.

결제 라이프사이클

pending → detected → succeeded · failed · expired

pending — 이체 대기 · detected — 온체인에서 감지, 확인 중 · succeeded — 지갑에 자금 확정(이 이벤트에 주문 처리) · failed / expired — 종결. 환불 변화는 웹훅 이벤트로 도착합니다.

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 unauthorizedmissing or invalid API key
404 not_foundunknown payment id (or a live id with a test key)
409 idempotency_conflictIdempotency-Key reused with a different body — identical retries replay the original response
422 (validation)malformed body — bad amount, unsupported currency
429 rate_limitedover the per-key budget: 100 writes/min, 1000 reads/min

상품, 결제 링크, 웹훅 엔드포인트, 환불은 대시보드에서 관리합니다 — 아직 공개 REST 엔드포인트가 없습니다.

웹훅

대시보드 「Webhooks」에서 엔드포인트를 추가하고 필요한 이벤트를 고르세요. 엔드포인트마다 whsec_… 서명 시크릿이 발급되며 생성 시 한 번만 표시됩니다.

payment.createdA payment intent was created (API or checkout link).
payment.detectedThe transfer was seen on-chain / in the KEM ledger; confirming.
payment.succeededFunds are confirmed in your business wallet. Fulfill on this event.
payment.failedThe payment failed.
payment.expiredThe checkout window closed without payment.
payment.refund.createdA refund was initiated from the dashboard.
payment.refund.succeededThe 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 헤더가 있습니다. 엔드포인트 시크릿으로 「<t>.」+원문 바디에 대한 HMAC을 재계산해 상수 시간으로 비교하고, 불일치는 거부하세요.

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| > 300s
import 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로 빠르게 응답하세요. 실패한 전송은 백오프로 재시도된 뒤 데드레터 처리됩니다:

1m · 5m · 30m · 2h · 12h · 24h

테스트

테스트 키로는 돈을 움직이지 않고 결제 전체 흐름을 진행할 수 있습니다 — 전환을 시뮬레이션하고 웹훅이 도착하는 것을 확인하세요:

curl -X POST https://api-business.kemapp.io/v1/payments/{id}/_simulate/succeeded \
  -H "Authorization: Bearer sk_test_..."
BUILT IN THE GULF · SETTLED IN USDT ·
kemBusiness

결제는
스테이블코인으로.

대시보드를 열고 오늘 첫 USDT 결제를 받아 보세요 — 또는 20분 통화로 함께 살펴봐 드립니다.

대시보드 열기↗통화 예약↗

이미 kem을 사용 중이신가요? 로그인

제품

  • 로그인
  • 계정 만들기
  • 데모 예약

모두를 위한 Kem

  • 소비자 앱
  • iOS — App Store
  • Android — Google Play

회사

  • Tether 투자
  • 개인정보 처리방침
  • 이용약관

© 2026 Kem · Kem은 바레인에 등록된 가상자산 서비스 제공자(CASP) 라이선스 보유 기업 KEM BAHRAIN W.L.L(상업등록번호 1-195589)를 통해 운영됩니다. [email protected]

걸프에서 제작.