API 레퍼런스
모든 엔드포인트는 서버에서 호출합니다. 요청과 응답은 JSON입니다. 웹훅 URL과 API 키는 가맹점 대시보드에서 관리합니다.
바로 복사해 쓸 코드가 필요하신가요? Node.js, Python, PHP, Go, Java 연동 예제
| 엔드포인트 | 용도 |
|---|---|
POST /v1/payment_intents | 결제 생성 |
GET /v1/payment_intents/{id} | 결제 조회 |
POST /v1/deposit_addresses | 사용자의 입금 주소 받기 |
GET /v1/deposits | 입금 기록 목록 |
GET /v1/deposits/{id} | 입금 기록 조회 |
GET /v1/chains | 프로젝트에서 쓸 수 있는 체인과 토큰 조회 |
PUT /v1/customers/{external_id} | 사용자에 태그와 메모 추가 (선택) |
GET /v1/customers/{external_id} | 사용자 조회 (선택) |
기본 규칙
| URL | https://api.kokiwa.com. 메인넷과 테스트넷이 같습니다. |
| 인증 | 헤더 Authorization: Bearer sk_…. sk_live_로 시작하는 키는 메인넷, sk_test_로 시작하는 키는 테스트넷에 접근하며 데이터는 완전히 분리됩니다. 키는 소속 프로젝트에만 접근할 수 있습니다. |
| 금액 | 토큰 수량 문자열입니다. 예: "25.00". 요청은 소수점 이하 최대 6자리이고, 응답은 온체인 정밀도를 유지하므로 자릿수가 일정하지 않습니다. 온체인 원시 값은 transaction.raw_amount뿐입니다. |
| 시간 | ISO 8601 UTC. 예: 2026-11-02T08:30:00Z. |
| 주소 형식 | EVM 주소는 EIP-55 체크섬 형식으로 반환됩니다. 그대로 표시하고, 비교할 때는 대소문자를 무시하세요. |
| 멱등성 | POST 요청에 Idempotency-Key(최대 255자)를 보낼 수 있습니다. 같은 키로 재시도하면 첫 결과가 반환되고 응답 헤더에 Idempotent-Replayed: true가 붙습니다. |
오류
실패하면 4xx 또는 5xx를 반환합니다. 오류 종류는 code로 판단하고, message는 디버깅에만 사용하세요.
{
"error": {
"code": "amount_below_minimum",
"message": "options[0].amount is below the minimum",
"details": { "min_amount": "5.00" }
}
}| HTTP | code | 의미 |
|---|---|---|
| 400 | invalid_* | 매개변수가 잘못되었습니다. message가 필드를 알려 줍니다. |
| 400 | chain_not_enabled | 이 체인에 유효한 수령 주소가 없거나 수납이 꺼져 있습니다. |
| 400 | chain_not_available | 이 체인은 현재 수납할 수 없습니다. |
| 400 | chain_not_supported | 이 체인에는 입금 주소가 없습니다. |
| 400 | token_not_enabled | 프로젝트가 이 토큰을 선택하지 않았습니다. |
| 400 | currency_not_available | 프로젝트가 어떤 체인에서도 이 통화를 받을 수 없습니다. |
| 400 | deposits_disabled | 프로젝트가 입금 주소를 껐습니다. |
| 400 | amount_below_minimum | 최소 수납 금액보다 적습니다. 최소 금액은 details.min_amount를 보세요. |
| 401 | unauthorized | API 키가 없거나, 유효하지 않거나, 폐기되었습니다. |
| 403 | project_disabled | 프로젝트가 비활성화되었습니다. |
| 404 | not_found | 리소스가 없거나 이 프로젝트의 것이 아닙니다. |
| 409 | request_in_progress | 같은 Idempotency-Key의 요청을 처리 중입니다. 잠시 후 다시 시도하세요. |
| 422 | idempotency_key_reused | 같은 Idempotency-Key가 다른 요청에 사용되었습니다. |
| 500 | internal_error | 서버 오류입니다. 나중에 같은 Idempotency-Key로 다시 시도하세요. |
결제
결제는 사용자가 지불할 주문 하나입니다. 사용자가 체크아웃에서 결제하면 결과를 웹훅으로 받습니다.
결제 생성
POST/v1/payment_intents| 매개변수 | 설명 |
|---|---|
currency 필수 | 통화. 예: USDT. GET /v1/chains의 currencies를 참고하세요. |
amount 필수 | 토큰 수량. 소수점 이하 최대 6자리. 예: "25.00". |
chains | 이 체인에서만 받습니다. 예: ["bsc", "base"]. 기본값은 프로젝트가 이 통화를 받을 수 있는 모든 체인입니다. |
customer | 내 시스템의 사용자 ID. 1~128자의 영문, 숫자, _ - . : @. |
expires_in | 유효 시간(초). 60~604800(7일), 기본값 1800(30분). |
metadata | 임의의 JSON 객체. 최대 50개 키, 8KB. API와 웹훅에 그대로 반환되며 주문 번호를 넣기 좋습니다. |
success_url | 결제 성공 후 체크아웃이 이동할 https URL. |
cancel_url | 사용자가 취소를 누를 때 이동할 https URL. |
최소 금액에 못 미치는 체인은 제외되고, 모든 체인이 못 미치면 오류가 납니다. 기본 최소 금액은 5달러이며, 내 수수료는 대시보드의 프로젝트 수수료 항목에서 확인할 수 있습니다.
체인별 토큰과 금액 지정
여러 통화를 받거나 체인마다 금액이 다르면 currency, amount, chains 대신 options를 씁니다. 최대 16개이며 token은 심볼이나 컨트랙트 주소입니다.
"options": [
{ "chain": "bsc", "token": "USDT", "amount": "25.00" },
{ "chain": "bsc", "token": "USDC", "amount": "25.00" }
]응답
201과 결제 객체를 반환합니다. checkout_url을 사용자에게 열어 주세요.
{
"id": "pi_7Gm4Rk2Wp9Ls1Qv8Bd3Zt6",
"object": "payment_intent",
"status": "pending",
"livemode": true,
"customer": "user_42",
"checkout_url": "https://pay.kokiwa.com/p/pi_7Gm4Rk2Wp9Ls1Qv8Bd3Zt6",
"metadata": { "order_id": "10086" },
"success_url": "https://your-shop.com/orders/10086",
"cancel_url": null,
"created_at": "2026-11-02T08:30:00Z",
"expires_at": "2026-11-02T09:00:00Z",
"paid_at": null,
"paid_option": null,
"options": [
{
"id": "pio_5Hq2Tz8rLw0aVb3Kc9XyN1",
"chain": "bsc",
"token": { "symbol": "USDT", "address": "0x55d3…7955", "decimals": 18 },
"amount": "25.00",
"received": "0.00",
"deposit_address": "0x8b1F…c04E"
},
{
"id": "pio_2Mn7Xc4bQe6uJs1Ga8RvK3",
"chain": "base",
"token": { "symbol": "USDT", "address": "0xfde4…9bb2", "decimals": 6 },
"amount": "25.00",
"received": "0.00",
"deposit_address": null
}
],
"deposits": []
}| 필드 | 설명 |
|---|---|
options | 사용자가 고를 수 있는 항목. 항목 하나가 체인 하나의 토큰 하나입니다. |
options[].received | 이 항목에서 받은 금액. |
options[].deposit_address | 이 결제 전용 송금 주소. 내 페이지에 직접 표시해도 됩니다. 이 방식이 없으면 null입니다(BNB Chain 이외의 체인 또는 너무 작은 금액). |
paid_option | 사용자가 실제로 결제한 options[].id. |
deposits | 이 결제로 받은 입금 기록. 오래된 순입니다. 입금 객체를 참고하세요. |
livemode | 메인넷은 true, 테스트넷은 false. |
결제 조회
GET/v1/payment_intents/{id}결제 객체를 반환합니다. 대사하거나 웹훅을 받지 못했을 때 상태를 확인하는 데 씁니다.
결제 상태
| status | 설명 |
|---|---|
pending | 결제 대기. |
partially_paid | 전용 주소로 보낸 금액이 부족해 amount − received가 남았습니다. 발송하지 마세요. 나머지를 내면 paid가 됩니다. |
paid | 전액 수령, 발송 가능. 초과 금액도 received에 포함되며 kokiwa가 자동 환불하지 않습니다. |
expired | 결제 없이 만료됨. |
paid_late | 만료 후 전용 주소로 입금되었습니다. 돈은 이미 내게 왔으니 발송할지 환불할지 결정하세요. |
입금 주소
고객 입금 주소 받기
POST/v1/deposit_addresses| 매개변수 | 설명 |
|---|---|
customer 필수 | 내 시스템의 사용자 ID. 규칙은 결제와 같습니다. 처음 사용할 때 자동 생성됩니다. |
chain | 현재 bsc만 지원하며 기본값입니다. |
{
"object": "deposit_address",
"customer": "user_42",
"chain": "bsc",
"address": "0x3c9A…71d2",
"tokens": [
{ "symbol": "USDT", "address": "0x55d3…7955", "decimals": 18, "min_settle_amount": "5.00" }
]
}같은 사용자에게는 항상 같은 주소가 반환되므로 오래 표시해도 됩니다. tokens에 있는 토큰만 입금 처리됩니다.
송금마다 deposit.confirmed를 보냅니다. min_settle_amount보다 적은 송금도 입금되며 상태는 held입니다. 이 주소의 누적액이 최소 금액에 이르면 수령 주소로 함께 회수되고 고정 수수료는 한 번만 부과됩니다.
입금 기록
입금 기록(deposit)은 반영된 온체인 결제 한 건으로, 결제 또는 입금 주소에서 발생합니다. 결제 하나에 여러 건이 있을 수 있습니다.
{
"id": "dep_9Kx2Pa6Wn3Ty8Lq5Rb1Ms4",
"object": "deposit",
"status": "settled",
"method": "wallet",
"chain": "bsc",
"customer": "user_42",
"payment_intent": "pi_7Gm4Rk2Wp9Ls1Qv8Bd3Zt6",
"token": { "symbol": "USDT", "address": "0x55d3…7955", "decimals": 18 },
"amount": "25.00",
"fee": "0.0875",
"net": "24.9125",
"usd_value": "25.00",
"confirmed_at": "2026-11-02T08:41:07Z",
"transaction": {
"hash": "0x4e7a…91c3",
"log_index": 212,
"block_number": 44718235,
"block_time": "2026-11-02T08:40:58Z",
"from": "0x1f9C…a2B0",
"to": "0x7d3E…09f1",
"raw_amount": "25000000000000000000"
},
"settlement": {
"tx_hash": "0x4e7a…91c3",
"by": "payment",
"settled_at": "2026-11-02T08:40:58Z"
}
}| 필드 | 설명 |
|---|---|
method | wallet: 지갑 결제. deposit_address: 주소로 송금. |
customer | 보낸 사용자 ID. 없으면 null. |
payment_intent | 소속 결제. 입금 주소의 기록은 null. |
amount、fee、net | 사용자가 낸 금액, 수수료, 실수령액. held 상태에서는 fee가 0이며 회수할 때 정해집니다. |
usd_value | amount를 kokiwa가 정한 토큰 가격으로 환산한 달러 금액. |
transaction | 사용자의 온체인 결제 트랜잭션으로, 블록 탐색기에서 확인할 수 있습니다. 한 트랜잭션에 송금이 여러 건이면 hash + log_index로 구분합니다. from이 사용자 본인 지갑이라는 보장은 없으며, 거래소 출금이면 거래소 주소입니다. raw_amount는 이 송금의 온체인 원시 값(토큰 최소 단위)으로, 블록 탐색기와 대조할 때만 씁니다. |
settlement | 수령 주소에 도착한 트랜잭션. 정산 전에는 null입니다. by는 payment(결제 자체로 정산), kokiwa(kokiwa가 회수), owner(내 지갑으로 회수, 수수료 없음)입니다. 함께 회수된 기록은 tx_hash가 같습니다. |
| status | 설명 |
|---|---|
confirmed | 온체인 확정, 수령 주소로 회수 대기. 사용자에게 입금 처리해도 됩니다. |
held | 온체인 확정, 금액이 작아 적립 중. 사용자에게 입금 처리해도 됩니다. |
settled | 수령 주소에 도착. |
입금 한 건 조회
GET/v1/deposits/{id}입금 목록
GET/v1/deposits최신순으로 반환합니다.
| 쿼리 매개변수 | 설명 |
|---|---|
customer | 특정 사용자만. |
tx_hash | 결제 또는 정산 트랜잭션 해시로 검색. |
limit | 페이지당 개수. 1~100, 기본값 20. |
starting_after | 이전 페이지 마지막 항목의 id. |
curl "https://api.kokiwa.com/v1/deposits?tx_hash=0x4e7a…91c3" \
-H "Authorization: Bearer $KOKIWA_KEY"
{ "object": "list", "data": [ { "id": "dep_9Kx2…", "object": "deposit", ... } ], "has_more": false }체인과 토큰
kokiwa가 지원하는 체인과 통화는 아래와 같습니다. chains와 options[].chain에는 chain 열의 값을, currency에는 통화 열의 값을 넣으세요.
chain | 블록체인 | 통화 | 결제 방식 |
|---|---|---|---|
bsc | BNB Chain | USDT, USDC | wallet, deposit_address |
ethereum | Ethereum | USDT, USDC | wallet |
arbitrum | Arbitrum | USDT, USDC | wallet |
base | Base | USDT, USDC | wallet |
polygon | Polygon | USDT, USDC | wallet |
optimism | Optimism | USDT, USDC | wallet |
ton | TON | USDT | wallet |
solana | Solana | USDT, USDC | wallet |
테스트넷은 USDT만 지원합니다. 토큰은 tUSDT이지만 currency는 그대로 USDT를 넣습니다.
이 표는 입력할 수 있는 값의 전체 범위이며, 프로젝트마다 모두 쓸 수 있다는 뜻은 아닙니다. 판매자마다 설정이 다르므로 실제 사용 가능한 체인과 통화는 아래 API로 조회하세요.
프로젝트의 체인과 토큰 조회
GET/v1/chains이 키의 프로젝트가 현재 네트워크에서 받을 수 있는 항목을 반환합니다.
{
"object": "list",
"livemode": true,
"currencies": ["USDT"],
"data": [
{
"object": "chain", "chain": "bsc", "name": "BNB Smart Chain", "chain_id": 56, "testnet": false, "native": "BNB",
"payout_registered": true, "active": true,
"methods": { "wallet": true, "deposit_address": true },
"tokens": [
{ "symbol": "USDT", "asset": "USDT", "address": "0x55d398326f99059fF775485246999027B3197955", "decimals": 18, "accepted": true },
{ "symbol": "USDC", "asset": "USDC", "address": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", "decimals": 18, "accepted": false }
]
}
]
}| 필드 | 설명 |
|---|---|
currencies | 지금 currency로 보낼 수 있는 통화. |
data[].chain | chain과 options[].chain에 쓰는 값: bsc, ethereum, arbitrum, base, polygon, optimism, ton, solana. |
data[].active | 이 체인이 지금 수납 가능한지: 수령 주소 등록, 수취 방식 켜기, 토큰 선택이 모두 끝났는지. |
data[].tokens[].asset | 토큰의 통화. asset이 같은 토큰은 체인이 달라도 동등합니다. |
data[].tokens[].accepted | 프로젝트가 이 토큰을 선택했는지. |
고객
선택 사항입니다. customer 값이 처음 나타나면 고객이 자동 생성됩니다. 대시보드에서 태그로 필터링할 때만 필요합니다.
라벨과 메모 설정
PUT/v1/customers/{external_id}| 매개변수 | 설명 |
|---|---|
tags | 태그 최대 20개, 각 1~64자의 영문, 숫자, _ - . :. |
metadata | 임의의 JSON 객체. 최대 50개 키, 8KB. |
고객 조회
GET/v1/customers/{external_id}태그, 메모, deposit_addresses(체인별 입금 주소)를 반환합니다.