개요
파트너는 출금 신청 시 정산 체인을 지정합니다. 신청이 접수되면 확정된 USDT 금액이 파트너 잔액에서 차감되고, 출금이 실패·반려·만료되면 원금과 수수료가 전액 환급됩니다.
/api/v1TRON, BSCpartnerOrderId인증
모든 원화 출금 Open API 요청에는 파트너 API 키로 만든 HMAC 인증 헤더 3개가 필요합니다.
| 헤더 | 값 |
|---|---|
X-API-KEY | 발급받은 파트너 API Key |
X-TIMESTAMP | Unix epoch 초. 밀리초가 아닙니다. |
X-ACCESS-TOKEN | 아래 서명식의 Base64 결과 |
message = X-TIMESTAMP + "." + X-API-KEY
signature = Base64(HMAC-SHA256(apiSecret, message))
- 서명 대상은
timestamp.apiKey뿐입니다. HTTP 메서드, 경로, 바디는 포함하지 않습니다. - 인코딩은 Base64입니다. hex 문자열이 아닙니다.
- 타임스탬프 허용 오차는 서버 시각 기준 ±300초입니다.
const crypto = require('crypto');
function authHeaders(apiKey, apiSecret) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const accessToken = crypto
.createHmac('sha256', apiSecret)
.update(`${timestamp}.${apiKey}`)
.digest('base64');
return {
'X-API-KEY': apiKey,
'X-TIMESTAMP': timestamp,
'X-ACCESS-TOKEN': accessToken,
'Content-Type': 'application/json'
};
}
공통 규칙
- 성공 응답은
data래퍼 없이 객체를 직접 반환합니다. - 값이 없는 필드는 응답에서 키 자체가 생략될 수 있습니다.
- 날짜/시각은 타임존 오프셋이 없는 ISO-8601 문자열입니다. 기준 타임존은 계약 시 별도 안내합니다.
- 소수부 뒤쪽 0은 생략될 수 있으므로 시각 문자열의 고정 길이에 의존하지 마십시오.
- API마다 금액 타입이 다릅니다. 각 응답 표의
number/string구분을 따르십시오. - 계좌번호, 예금주, 은행 코드는 신청 응답이나 조회 응답에 다시 포함되지 않습니다.
에러 응답
description과 data는 오류에 따라 생략될 수 있습니다.
{
"code": "1123",
"message": "원화 출금 주문을 찾을 수 없습니다.",
"description": "orderCode=kwo_example"
}
출금 상태
| 상태 | 의미 | 파트너 잔액 |
|---|---|---|
| WAITING | 접수 완료, 승인 대기 | 차감 유지 |
| APPROVED | 승인 완료, 지급 처리 중 | 차감 유지 |
| SETTLING | 원화 지급 완료, 최종 처리 중 | 차감 확정 |
| COMPLETED | 출금 완료 | 차감 확정 |
| FAILED | 회수, 승인 기한 만료 또는 지급 실패 | 전액 환급 |
| REJECTED | 승인 전 개별 반려 | 전액 환급 |
APPROVED부터는 원화 지급이 진행될 수 있으므로 파트너 회수 요청이 409로 거부됩니다.
API Reference
회원에게 지급할 원화 금액과 계좌 정보를 전달합니다. 신청이 접수된 시점에 원금과 수수료가 파트너 USDT 잔액에서 차감됩니다.
Request body
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
partnerUserId | string | Y | 파트너 사용자 식별자, 최대 100자 |
partnerOrderId | string | Y | 파트너 주문 멱등키, 최대 100자 |
krwAmount | number | Y | 정수, 10,000~9,000,000 KRW |
chain | string | Y | TRON 또는 BSC |
bankCode | string | Y | 아래 표의 3자리 은행 코드 |
accountNumber | string | Y | 수취 계좌번호, 최대 50자 |
accountHolder | string | Y | 예금주, 최대 50자 |
은행 코드
bankCode에는 다음 3자리 코드를 사용하십시오. 2026-09-20 기준 활성 은행 카탈로그입니다.
| 코드 | 은행명 | 코드 | 은행명 |
|---|---|---|---|
002 | KDB산업은행 | 003 | IBK기업은행 |
004 | KB국민은행 | 007 | Sh수협은행 |
011 | NH농협은행 | 020 | 우리은행 |
023 | SC제일은행 | 031 | iM뱅크 |
032 | BNK부산은행 | 034 | 광주은행 |
035 | 제주은행 | 037 | 전북은행 |
039 | BNK경남은행 | 045 | 새마을금고 |
048 | 신협 | 071 | 우체국 |
081 | 하나은행 | 088 | 신한은행 |
089 | 케이뱅크 | 090 | 카카오뱅크 |
092 | 토스뱅크 |
{
"partnerUserId": "user-001",
"partnerOrderId": "krw-20260920-0001",
"krwAmount": 10000,
"chain": "BSC",
"bankCode": "004",
"accountNumber": "000000000000",
"accountHolder": "테스트"
}
Response
| 필드 | 타입 | 설명 |
|---|---|---|
orderCode | string | Cryptoments 주문 코드. 이후 조회와 회수에 사용 |
status | string | 접수 직후 WAITING |
krwAmount | number | 회원에게 지급할 원화 금액 |
chain | string | 정산 체인 |
exchangeRate | number | 신청 시 확정된 KRW/USDT 환율 |
debitUsdt | number | 파트너 잔액 총 차감액 = 원금 + 수수료 |
feeUsdt | number | 파트너 부담 수수료 |
ttlExpiresAt | string | 승인 기한. 승인 후 생략 |
txHash | string | 완료 후 제공. 이전에는 생략 |
{
"orderCode": "kwo_example0001",
"status": "WAITING",
"krwAmount": 10000,
"chain": "BSC",
"exchangeRate": 1369.0000,
"debitUsdt": 7.377647918188458728,
"feeUsdt": 0.073046018991964937,
"ttlExpiresAt": "2026-09-20T18:39:40"
}
partnerOrderId의 비종결 주문이 있으면 기존 주문을 200 OK로 반환하며 잔액을 다시 차감하지 않습니다. 주문이 COMPLETED, FAILED, REJECTED로 종결된 뒤에는 같은 값으로도 새 주문이 생성될 수 있습니다. 서로 다른 출금에는 절대 같은 값을 재사용하지 마십시오.
주요 응답 코드
| 201 | 신규 접수 성공 |
| 200 | 동일 partnerOrderId의 비종결 주문 반환 |
| 401 | 인증 실패 또는 타임스탬프 만료 |
| 404 | 체인 또는 통화 설정 없음 |
| 409 | 시세, 잔액, 지갑 또는 접수 조건 불충족 |
| 422 | 금액 범위 또는 요청 필드 검증 실패 |
WAITING 상태의 신청을 회수합니다. 요청 바디는 없습니다. 성공하면 원금과 수수료가 즉시 전액 환급되고 주문은 FAILED로 종결됩니다.
APPROVED인 주문은 원화 지급이 진행될 수 있어 회수할 수 없습니다.
응답
응답 필드는 출금 신청 응답과 같습니다. 이미 FAILED인 주문을 다시 호출해도 200을 반환합니다.
| 200 | 회수 성공 또는 이미 실패 종결된 주문 |
| 404 / 1123 | 주문 없음. 다른 파트너 주문도 404 |
| 409 / 1125 | 이미 승인되어 회수 불가 |
| 409 / 1124 | 완료·반려 등 다른 종결 상태 |
| 409 / 1127 | 접수 확정 중. 잠시 후 재시도 |
파트너가 직접 호출한 회수에는 별도 상태 웹훅을 보내지 않습니다. 회수 API 응답으로 처리 결과를 확정하십시오.
주문의 현재 상태를 조회합니다. 웹훅은 유실되거나 중복될 수 있으므로 최종 상태를 확정할 때 이 API를 사용하십시오.
응답
응답 필드는 출금 신청 응답과 같습니다. 완료 전에는 txHash가 생략됩니다.
{
"orderCode": "kwo_example0001",
"status": "COMPLETED",
"krwAmount": 10000,
"chain": "BSC",
"exchangeRate": 1369.0000,
"debitUsdt": 7.377647918188458728,
"feeUsdt": 0.073046018991964937,
"txHash": "0xabc123..."
}
| 200 | 조회 성공 |
| 404 / 1123 | 주문 없음. 다른 파트너 주문도 404 |
GET /api/v1/krw-withdrawals?from=2026-09-20&to=2026-09-20&status=COMPLETED&page=1&size=20
Query parameters
| 파라미터 | 필수 | 설명 |
|---|---|---|
from | N | 신청 시각 시작. 날짜 또는 ISO-8601 로컬 시각 |
to | N | 신청 시각 끝. 날짜만 주면 해당 날짜 전체를 포함하고, 시각을 주면 미만 조건 |
status | N | 출금 상태 |
page | N | 1부터 시작, 기본 1 |
size | N | 페이지 크기, 기본 20 |
기간을 생략하면 전체 기간을 조회합니다. 기본 정렬은 신청 시각 내림차순입니다.
Response
{
"pageRows": [
{
"orderCode": "kwo_example0001",
"partnerOrderId": "krw-20260920-0001",
"partnerUserId": "user-001",
"status": "COMPLETED",
"krwAmount": "10000",
"chain": "BSC",
"exchangeRate": 1369.0000,
"debitUsdt": 7.377647918188458728,
"feeUsdt": 0.073046018991964937,
"txHash": "0xabc123...",
"createdAt": "2026-09-20T18:09:24",
"approvedAt": "2026-09-20T18:10:00",
"completedAt": "2026-09-20T18:12:00"
}
],
"page": 1,
"size": 20,
"offset": 0,
"hasNext": false,
"totalCount": 1,
"orders": [
{ "direction": "DESC", "column": "o.created_at" }
]
}
krwAmount는 number지만 목록 행에서는 string입니다. 파서는 두 응답 계약을 구분해야 합니다.
목록 전용 필드
| 필드 | 타입 | 설명 |
|---|---|---|
partnerOrderId | string | 파트너 주문 멱등키 |
partnerUserId | string | 파트너 사용자 식별자 |
closeReason | string | 실패·반려 종결 사유. 정상 진행/완료 시 생략 |
createdAt | string | 신청 시각 |
approvedAt | string | 승인 시각 |
completedAt | string | 완료 시각 |
closedAt | string | 실패·반려 종결 시각 |
closeReason 코드
RECALLED | 파트너 회수 |
TTL_EXPIRED | 승인 기한 만료 |
ACCEPT_TIMEOUT | 접수 결과 불명 후 자동 환급 |
SOLUTION_REJECTED | 접수 거부 |
VAP_REJECTED | 승인 전 개별 반려 |
PAYOUT_FAILED | 원화 지급 실패 |
ACCEPT_ORPHANED | 접수 확정 중 중단된 주문 정리 |
closeReason에는 상세 사유가 뒤에 추가될 수 있습니다. 전체 문자열 일치보다 코드 접두부를 기준으로 분기하십시오.
상태 웹훅
파트너가 등록한 웹훅 URL로 최종 상태를 통지합니다. 웹훅은 보조 수단이며, 최종 확인은 단건 조회 API를 사용하십시오.
| event | 발생 시점 |
|---|---|
KRW_WITHDRAWAL_COMPLETED | 출금 완료 |
KRW_WITHDRAWAL_FAILED | 승인 기한 만료 또는 지급 실패 |
KRW_WITHDRAWAL_REJECTED | 승인 전 개별 반려 |
{
"event": "KRW_WITHDRAWAL_COMPLETED",
"orderCode": "kwo_example0001",
"status": "COMPLETED",
"partnerUserId": "user-001",
"krwAmount": 10000,
"exchangeRate": "1369.0000",
"debitUsdt": "7.377647918188458728",
"feeUsdt": "0.073046018991964937",
"chainType": "BSC",
"txHash": "0xabc123...",
"occurredAt": "2026-09-20T18:13:28.51"
}
krwAmount는 number입니다.exchangeRate,debitUsdt,feeUsdt는 정밀도 보존을 위한 string입니다.- 실패·반려 이벤트에는
reason이 포함되며txHash는 생략될 수 있습니다. - 계좌번호, 은행 코드, 예금주는 웹훅에 포함되지 않습니다.
- 파트너가 직접 호출한 회수에는 웹훅을 보내지 않습니다.
event, orderCode, status 조합으로 멱등 처리하고 최종 상태는 단건 조회 API로 확인하십시오.
| 파트너 응답 | 처리 |
|---|---|
| HTTP 2xx | 전달 성공 |
| 모든 비-2xx, 타임아웃, 연결 실패 | 실패로 처리하고 재시도 |
최초 전송을 포함해 최대 5회 시도합니다. 파트너 수신 서버는 중복 전달을 허용해야 합니다.
오류 코드
| HTTP | code | 의미 | 권장 조치 |
|---|---|---|---|
| 422 | — | 금액 범위 또는 요청 필드 검증 실패 | 10,000~9,000,000원과 필수 필드 확인 |
| 409 | 1121 | 시세 편차 초과 | 잠시 후 새 요청 검토 |
| 409 | 1122 | 출금 요청이 접수되지 않음 | 차감은 환급됨. 사유 확인 후 재신청 |
| 404 | 1123 | 주문을 찾을 수 없음 | 주문 코드와 소유 파트너 확인 |
| 409 | 1124 | 이미 종결된 주문 | 목록 또는 단건 조회로 상태 확인 |
| 409 | 1125 | 이미 승인된 주문 | 회수 불가 |
| 409 | 1127 | 접수 확정 중 | 잠시 후 같은 요청 재시도 |
| 409 | 1128 | 지정 체인 출금 지갑 미준비 | 다른 체인 사용 여부를 별도 판단 |
| 409 | INSUFFICIENT_BALANCE | 지정 체인 가용 잔액 부족 | 잔액 충전 후 재신청 |
인증 실패는 401, 요청 필드 검증 실패는 422입니다. 같은 HTTP 상태라도 의미가 다를 수 있으므로 반드시 응답의 code로 분기하십시오.
연동 체크리스트
X-TIMESTAMP를 epoch 초로 보내는지 확인합니다.X-ACCESS-TOKEN을 Base64 HMAC으로 생성하는지 확인합니다.partnerOrderId는 출금 의도마다 고유하게 만들고 다른 출금에 재사용하지 않습니다.- 동일 키 재호출은 기존 주문이 비종결 상태일 때만 멱등합니다. 응답 유실 후 시간이 지났다면 자동 재신청하지 말고 목록의
partnerOrderId로 먼저 대조합니다. chain별 잔액을 구분하고 자동 폴백을 가정하지 않습니다.- 목록 응답의
krwAmount문자열을 허용합니다. - 응답의 optional 필드가 키째 생략되어도 파싱할 수 있게 합니다.
- 웹훅은 중복 처리하고, 상태 확정은 단건 조회 API로 수행합니다.
- 운영 전 정상 완료·승인 전 회수·실패/반려 시나리오를 각각 검증합니다.