인증 방식 개요
CRYPTOMENTS Open API는 HMAC-SHA256 서명 인증을 사용합니다. 파트너 콘솔에서 발급받은 API Key와 Secret Key 쌍으로 각 요청에 서명합니다. 서버는 동일한 알고리즘으로 서명을 재계산하여 요청의 진위를 검증합니다.
인증 헤더
인증이 필요한 모든 요청에 아래 3개 헤더를 포함해야 합니다:
| 헤더 | 타입 | 설명 | 예시 |
|---|---|---|---|
X-API-KEY |
String | 파트너 콘솔에서 발급받은 API Key | pk_live_a1b2c3d4e5f6... |
X-TIMESTAMP |
String (ms) | 요청 시각의 Unix Epoch (밀리초). 서버 시간과 5분 이내 차이만 허용됩니다. | 1711785600000 |
X-SIGNATURE |
String (Hex) | HMAC-SHA256 서명 결과 (소문자 hex, 64자) | a1b2c3...f6e5d4 |
추가로 Content-Type: application/json 헤더는 모든 요청에 포함해야 합니다.
서명 알고리즘
서명은 아래 순서로 생성합니다:
timestamp + HTTP Method (대문자) + 요청 경로 + 요청 Body 를 문자열로 연결합니다. GET 요청처럼 Body가 없는 경우 빈 문자열을 사용합니다.
Secret Key를 키로, rawString을 메시지로 사용하여 HMAC-SHA256 해시를 생성합니다.
해시 결과를 소문자 hexadecimal 문자열로 변환하여 X-SIGNATURE 헤더에 설정합니다.
// 서명 공식 rawString = timestamp + method + path + body signature = hex(HMAC_SHA256(secretKey, rawString)) // 예시 timestamp = "1711785600000" method = "POST" path = "/api/v1/users/deposit-wallet" body = '{"chainType":"BSC","currencyType":"USDT"}' rawString = "1711785600000" + "POST" + "/api/v1/users/deposit-wallet" + body signature = hex(HMAC_SHA256("sk_live_...", rawString)) = "a3f8b1c2d4e5..." // 64자 hex
rawString = "1711785600000GET/api/v1/partner/balances"
코드 예제
const crypto = require('crypto'); const API_KEY = 'pk_live_a1b2c3d4e5f6'; const SECRET_KEY = 'sk_live_x9y8z7w6v5u4'; async function callApi(method, path, body = '') { const timestamp = Date.now().toString(); const bodyStr = body ? JSON.stringify(body) : ''; const rawString = timestamp + method + path + bodyStr; const signature = crypto .createHmac('sha256', SECRET_KEY) .update(rawString) .digest('hex'); const res = await fetch(`https://api.cryptoments.cc${path}`, { method, headers: { 'X-API-KEY': API_KEY, 'X-TIMESTAMP': timestamp, 'X-SIGNATURE': signature, 'Content-Type': 'application/json', }, body: bodyStr || undefined, }); return res.json(); } // 사용 예: 입금 지갑 생성 const result = await callApi('POST', '/api/v1/users/deposit-wallet', { chainType: 'BSC', currencyType: 'USDT', partnerUserId: 'user_001', }); console.log(result); // → { success: true, data: { address: "0x...", chainType: "BSC", ... } }
import hmac, hashlib, json, time, requests API_KEY = 'pk_live_a1b2c3d4e5f6' SECRET_KEY = 'sk_live_x9y8z7w6v5u4' BASE_URL = 'https://api.cryptoments.cc' def call_api(method, path, body=None): timestamp = str(int(time.time() * 1000)) body_str = json.dumps(body) if body else '' raw = timestamp + method + path + body_str signature = hmac.new( SECRET_KEY.encode(), raw.encode(), hashlib.sha256 ).hexdigest() headers = { 'X-API-KEY': API_KEY, 'X-TIMESTAMP': timestamp, 'X-SIGNATURE': signature, 'Content-Type': 'application/json', } resp = requests.request(method, BASE_URL + path, headers=headers, data=body_str) return resp.json() # 사용 예: 파트너 잔액 조회 (GET, body 없음) result = call_api('GET', '/api/v1/partner/balances') print(result) # 사용 예: 출금 요청 (POST) result = call_api('POST', '/api/v1/users/withdrawal', { 'chainType': 'BSC', 'currencyType': 'USDT', 'toAddress': '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18', 'amount': '100.00', 'partnerUserId': 'user_001', })
curl -X POST https://api.cryptoments.cc/api/v1/users/deposit-wallet \ -H "Content-Type: application/json" \ -H "X-API-KEY: pk_live_a1b2c3d4e5f6" \ -H "X-TIMESTAMP: 1711785600000" \ -H "X-SIGNATURE: a3f8b1c2d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0" \ -d '{"chainType":"BSC","currencyType":"USDT","partnerUserId":"user_001"}'
인증 오류 처리
인증에 실패하면 HTTP 401 응답이 반환됩니다. 주요 오류 원인:
| 에러 코드 | 원인 | 해결 방법 |
|---|---|---|
1001 |
유효하지 않은 API Key | 파트너 콘솔에서 API Key 확인. 비활성화된 키가 아닌지 확인 |
1002 |
서명 불일치 | rawString 생성 순서 확인 (timestamp+method+path+body). Secret Key 오타 확인 |
EXPIRE_ACCESS_TOKEN |
타임스탬프 만료 (5분 초과) | 서버 시간과 동기화. NTP 사용 권장 |
1003 |
비활성 파트너 | 파트너 계정 상태를 관리자에게 문의 |
위젯 토큰 인증
위젯 API (/widgets/api/*) 경로는 HMAC 인증 대신 위젯 토큰을 사용합니다. 서버에서 POST /widgets/auth/token으로 토큰을 발급받고, 클라이언트가 Authorization: Bearer {token} 헤더로 인증합니다.
/api/v1/* 엔드포인트 → HMAC-SHA256 서명 (서버 ↔ 서버)
/widgets/auth/token → HMAC-SHA256 서명으로 토큰 발급 (서버 → CRYPTOMENTS)
/widgets/api/* 엔드포인트 → Bearer 토큰 (클라이언트 → CRYPTOMENTS)