Docs Sandbox API

Unifi Pay API를 연동하는 개발자를 위한 API 레퍼런스 입니다. REST API를 통해 스테이블코인 결제 생성부터 정산까지 연동하는 방법을 상세히 설명합니다. 연동 프로세스 및 비즈니스 정보는 Guides 페이지를 참고해 주세요.

빠른 연동

SDK 없이 REST API만으로 결제 연동 완료

HMAC 보안

API 요청 시 HMAC 서명 인증 적용

Webhook 지원

비동기 Webhook으로 실시간 결제 상태 수신

AI 연동 가이드

AI 코딩 어시스턴트에 제공하면 API 연동 작업에 참고 자료로 활용할 수 있습니다.

PDF 다운로드
1 PDF를 다운로드합니다.
2 Claude Code, Codex CLI, Gemini CLI 등 AI 코딩 어시스턴트에 파일로 제공합니다.
3 "이 문서를 참고해서 결제 연동 코드를 작성해줘"처럼 요청합니다.

1. API 연동 다이어그램

결제 링크 발급 방식의 가맹점 서버·고객·Unifi Pay 간 데이터 흐름입니다.

1.1 결제 다이어그램

결제 링크 발급부터 Webhook 수신까지의 전체 흐름입니다.

동기 호출 (Sync)
응답 (Response)
비동기 Webhook (Async)
Customer (Browser) Your Server Backend Unifi Pay API Server 1 POST /api/seller/v1/payment/link X-API-Key · X-Timestamp · X-Authorization-Hmac 2 200 OK — linkUrl, linkId 3 고객에게 결제 링크 공유 linkUrl Unifi Pay 결제 링크 페이지 4 결제 링크 접속 5 ‘결제 진행하기’ 클릭 시 결제 요청 생성 transactionId (UUID) · orderId = LINK-{linkId}-{randomstring} 6 지갑 연결 및 결제 승인 온체인 전송 7 POST {callbackUrl} callbackUrl 등록 시에만 전송 status: CONFIRMED / FAILED / CANCELED [Async Webhook]

Your Server: apiKeyHMAC Signature를 이용해 Unifi Pay에 결제 링크 발급을 요청합니다.

결제 링크: 발급받은 linkUrl을 고객에게 공유합니다. 공유 채널에는 제한이 없습니다.

Customer: 링크에 접속해 결제를 진행하면 결제 요청이 생성되고, 지갑 연결 및 서명으로 결제가 완료됩니다.

Webhook: 결제 링크 발급 시 callbackUrl을 등록한 경우에만 전송됩니다. 등록하지 않으면 결제 상태 확인 API로 조회해야 합니다.


2. API 상세 소개

Base URL
Preview https://app-api-pay.unifi.me
Production https://api-pay.unifi.me

2.1 인증 (Authentication)

서버 간 API 요청은 기본적으로 HMAC 인증이 필수입니다. X-Authorization-Hmac 헤더에 서명값을 포함해야 합니다. X-Authorization-Hmac

기본 인증 규칙: 별도 표기가 없는 한 서버 간 API 는 모두 HMAC 인증이 기본입니다. 인증 방식이 다른 API(예: 무인증 공개 API)는 해당 API 에 별도로 표기합니다.

HMAC 생성 공식

Formula
BASE64(HMACSHA256(apiSecret, {HTTP_METHOD}{URI}{X-API-Key}{X-Timestamp}{REQUEST_BODY}))
REQUEST_BODY가 있는 경우
POST /api/seller/v1/payment/link
요청 예시
request header:
  X-API-Key:            "b6ef2f7c-3e74-438c-b456-689e821992be"
  X-Timestamp:          1773017787000
  X-Authorization-Hmac: "some-hmac-signature"
request body:
{
  "requestId": "REQ-20260304-0001",
  "storeId": "123",
  "serviceName": "MyShop",
  "itemName": "ITEM-GAME-001",
  "itemPrice": 12.34,
  "orderCurrencyCode": "USD",
  "returnUrl": "https://myshop.com/payment/returnUrl",
  "callbackUrl": "https://myshop.com/payment/callbackUrl",
  "expiresAt": "2026-08-31T00:00:00Z"
}
서명 생성
X-Authorization-Hmac = Base64(
  HmacSHA256(
    apiSecret,
    "POST"                                    ← HTTP_METHOD
    + "/api/seller/v1/payment/link"           ← URI
    + "b6ef2f7c-3e74-438c-b456-689e821992be" ← X-API-Key
    + "1773017787000"                         ← X-Timestamp
    + "{"requestId":"REQ-20260304-0001","storeId":"123","serviceName":"MyShop","itemName":"ITEM-GAME-001","itemPrice":12.34,"orderCurrencyCode":"USD","returnUrl":"https://myshop.com/payment/returnUrl","callbackUrl":"https://myshop.com/payment/callbackUrl","expiresAt":"2026-08-31T00:00:00Z"}"       REQUEST_BODY (공백 없이)
  )
)
REQUEST_BODY가 없는 경우
GET /api/seller/v1/payment/123
요청 예시
request header:
  X-API-Key:            "b6ef2f7c-3e74-438c-b456-689e821992be"
  X-Timestamp:          1773017787000
  X-Authorization-Hmac: "some-hmac-signature"
서명 생성
X-Authorization-Hmac = Base64(
  HmacSHA256(
    apiSecret,
    "GET"                                     ← HTTP_METHOD
    + "/api/seller/v1/payment/123"            ← URI
    + "b6ef2f7c-3e74-438c-b456-689e821992be" ← X-API-Key
    + "1773017787000"                         ← X-Timestamp
                                              REQUEST_BODY 없음 (생략)
  )
)

요청 헤더 파라미터

파라미터 타입 필수 설명
X-Authorization-HmacSTRING필수생성된 HMAC 서명값. 모든 서버 간 API 요청에 필수입니다.
X-API-KeySTRING필수Unifi Pay에서 발급받은 apiKey.
X-TimestampSTRING필수밀리초 단위 Unix 타임스탬프. 현재 시각과 5분 이상 차이 시 요청이 거부됩니다.
⚠️ 타임스탬프 유효 범위: X-Timestamp는 현재 서버 시각에서 5분 이내여야 합니다. 이 범위를 벗어나면 재전송 공격(Replay Attack) 방지를 위해 요청이 자동으로 거부됩니다.
서버 timestamp 조회

Unifi pay 서버의 timestamp를 조회하여 서버 상태를 확인하고, 응답의 timestamp 값을 HMAC 서명에 활용합니다.

GET /api/v1/server/time

응답 필드

필드 타입 설명
timestampINTEGER(INT64)서버의 timestamp 밀리초 단위 값

응답 예시

정상 응답 · 200 OK
{
  "timestamp": 1773017787000
}
오류 응답 · 500 Internal Server Error
{
  "code": "INTERNAL_SERVER_ERROR",
  "message": ""
}

2.3 결제 상태 확인 API

생성된 결제 건의 현재 상태를 확인합니다.

GET /api/seller/v1/payment/{transactionId}

응답 필드

필드 타입 설명
transactionIdSTRINGUnifi Pay에서 생성한 거래 번호.
orderIdSTRING가맹점 거래에 대한 ID 정보.
storeIdSTRING요청자가 제공하는 가맹점 ID 정보.
serviceNameSTRING결제창에 노출될 서비스 또는 가맹점 정보.
statusSTRING
CREATED결제 생성 완료
PENDING결제 진행 중
CONFIRMED결제 성공 (종결)
FAILED결제 실패 (종결)
CANCELED결제 취소 (종결)
failTypeSTRING

status가 FAILED일 때 설정됩니다.

WALLET_PURCHASE_BLOCKCHAIN_FAILEDunifi wallet에서 blockchain 출고 과정 중 실패
WALLET_PURCHASE_INSUFFICIENT_BALANCE사용자 지갑의 잔고 부족
PAYMENT_PURCHASE_BLACKLISTED사용자의 지갑이 payment 블랙리스트에 포함되어 실패
UNKNOWN결제 과정 중 알 수 없는 오류
items Array — 결제 상품 목록 최대 1건
↳ nameSTRING판매 상품의 식별 정보.
↳ priceDOUBLE판매 상품의 가격.
orderCurrencyCodeSTRINGISO 4217를 따르는 주문 통화 코드. 현재 "USD"로 고정됩니다.
orderAmountDOUBLE주문한 금액.
payCurrencyCodeSTRING결제한 스테이블 코인 종류.
payAmountDOUBLE결제된 금액.
blockchainTxIdSTRING블록체인 트랜잭션 해시. 결제가 최종 성공(CONFIRMED)했거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다.
blockchainNetworkFeeDOUBLE블록체인 네트워크 수수료. 결제 성공(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.)

응답 예시

JSON
{
  "transactionId": "<uuid>",
  "orderId": "<orderId>",
  "storeId": "<storeId>",
  "serviceName": "<serviceName>",
  "items": [
    {
      "name": "ITEM-GAME-001",
      "price": 50000
    }
  ],
  "status": "CONFIRMED",
  "failType": null,
  "countryCode": "KOR",
  "payAmount": 49000,
  "payCurrencyCode": "USDT",
  "orderAmount": 50000,
  "orderCurrencyCode": "USD",
  "blockchainTxId": "0x4fce0d72ff7f4b9f4ba0cf58d30119924bea3811d85a830c762e1d87b3e1ee17",
  "blockchainNetworkFee": 0.00253778
}
CONFIRMED

결제가 성공적으로 완료되어 확정된 상태입니다.

FAILED

결제가 실패한 상태입니다.

오류 응답

HTTP 상태 오류 코드 설명
400 BAD_REQUEST 유효하지 않은 입력 값
401 UNAUTHORIZED 유효하지 않은 HMAC일 경우
403 FORBIDDEN 허용되지 않은 IP 혹은 Path 일 경우
503 MAINTENANCE 점검 중일 경우
406 PAYMENT_TRANSACTION_NOT_FOUND 유효하지 않은 transactionId
500 INTERNAL_SERVER_ERROR 서버 내부 오류

2.4 결제 Webhook

생성한 결제 건에 대한 결제 완료 여부를 비동기로 수신합니다.

POST <가맹점 callbackUrl>

요청 바디 필드

필드 타입 필수 설명
transactionIdSTRING필수Unifi Pay에서 생성한 거래 번호.
orderIdSTRING필수Unifi Pay에서 생성한 주문 id. 결제 링크를 통한 거래는 LINK-{linkId}-{임의 문자열} 형식으로 발급되며, 고객이 결제 링크에서 결제를 진행한 시점에 결정됩니다.
statusSTRING필수결제 처리 결과. CONFIRMED / FAILED / CANCELED.
typeSTRING필수거래 유형. 환불을 API로 제공하지 않으므로 항상 PURCHASE입니다.

요청 예시 (JSON)

JSON
{
  "transactionId": "<uuid>",
  "orderId": "LINK-3f1d0a549c1e4f6a8a5b2f-a1b2c3",
  "status": "CONFIRMED",
  "type": "PURCHASE"
}
📡 응답 필수 안내: 가맹점 서버는 Webhook 수신 후 반드시 HTTP 200 OK 응답 코드를 반환해야 합니다.
💡 상세 조회: Webhook은 최소한의 정보만 전달합니다. 결제 상세 정보는 Webhook 수신 후 2.3 결제 상태 확인 API를 호출하여 조회하세요.

재시도 정책

가맹점 서버에서 5xx 오류 또는 응답이 없을 경우, 아래 정책에 따라 재전송됩니다.

순서 재시도 시점
1차 재시도 3초 후
2차 재시도 30초 후
3차 재시도 10분 후
4차 재시도 1시간 후
5차 재시도 3시간 후

2.5 환불 (콘솔 처리)

환불은 API로 제공되지 않습니다. 지갑 서명이 필요한 처리이므로 콘솔에서만 실행할 수 있습니다.

처리 방법: 판매자가 Unifi Pay 콘솔의 환불 관리 메뉴에서 본인 명의의 Unifi Wallet으로 직접 서명하여 실행합니다.

연동 시 참고 사항

항목 설명
환불 Webhook제공하지 않습니다. 환불 처리 결과는 Webhook으로 전송되지 않으므로 결제 내역 API로 조회해야 합니다.
환불 내역 조회아래 2.6 결제 내역 API에서 paymentType=REFUND 로 조회합니다.
원결제 연결환불 건의 originTransactionId 가 원결제의 transactionId 를 가리킵니다.
💡 참고: 환불 지갑·환불 금액 기준·주소 및 네트워크 조건 등 환불 정책은 이용 가이드 5. 환불(송금 보조 기능)을 참고하시기 바랍니다.

2.6 결제 내역 API

결제, 환불 내역을 확인합니다.

GET /api/seller/v1/payment/settlement/transaction

요청 쿼리 파라미터

파라미터 타입 필수 설명
fromSTRING조건부조회 시작일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-01T00:00:00Z). transactionId/settlementId 미지정 시 필수이며, to보다 이전 시점 설정 필수.
toSTRING조건부조회 종료일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-31T23:59:59Z). transactionId/settlementId 미지정 시 필수이며, 조회 기간은 최대 90일까지 허용.
paymentTypeSTRING선택결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체
transactionIdSTRING선택Unifi Pay에서 생성한 거래 번호. from/to/settlementId 미지정 시 필수.
settlementIdSTRING선택Unifi Pay 지급 명세서 ID 정보. from/to/transactionId 미지정 시 필수.
pageINTEGER선택페이지 번호 (0부터 시작, 기본값: 0)
sizeINTEGER선택페이지 크기 (기본값: 20)

응답 필드 (200 OK)

필드 이름 타입 필수 설명
contentList필수결제 데이터 목록
↳ partnerCorpNameSTRING필수법인명 (EN)
↳ storeIdSTRING선택가맹점 ID 정보
↳ orderIdSTRING필수거래에 대한 ID 정보
↳ itemNameSTRING필수상품의 식별 정보
↳ serviceNameSTRING선택서비스 또는 가맹점명 (EN)
↳ orderCountryCodeSTRING필수구매자 국가 코드
↳ orderCurrencyCodeSTRING필수ISO 4217를 따르는 주문 통화 코드
↳ orderAmountDOUBLE필수주문 금액
↳ createdAtINSTANT필수주문 결제 요청 일시
↳ transactionIdSTRING필수Unifi Pay에서 생성한 거래 번호.
↳ blockchainTxIdSTRING필수KaiaScan TxID
↳ paymentTypeSTRING필수결제: PURCHASE / 환불: REFUND
↳ originTransactionIdSTRING선택환불 시 원 거래 번호 (REFUND인 경우 필수, PURCHASE인 경우 Null)
↳ statusSTRING필수CONFIRMED 고정 (CONFIRMED건만 조회)
↳ finalizedAtINSTANT필수주문 결제 최종 상태 일시
↳ capturedAtINSTANT필수주문 결제 완료 일시
↳ failTypeSTRING선택주문 결제 실패 사유
↳ payCurrencyCodeSTRING필수실 결제 통화 USDT
↳ payAmountDOUBLE필수실 결제 금액
↳ paymentExchangeRateDOUBLE필수결제 시점 환율. 결제 통화와 주문 통화가 다를 때 적용되며, 같으면 1입니다. (기준 통화: payCurrencyCode)
↳ buyerWalletAddressSTRING필수구매자 결제 지갑 주소
↳ variableFeeRateDOUBLE선택결제 수수료율 (%). Unifi Pay 지급 명세서 번호 생성 전인 경우 Null
↳ settlementIdSTRING선택Unifi Pay 지급 명세서 ID 정보. 생성 전인 경우 Null
↳ settlementCurrencyCodeSTRING선택정산 통화 코드 (USDT, JPYC). 정산 전인 경우 Null
↳ settlementExchangeRateDOUBLE선택정산 시점 환율. 정산 전인 경우 Null
totalElementsLONG필수전체 건수
totalPagesINTEGER필수전체 페이지수
pageNumberINTEGER필수현재 페이지 번호
firstBOOLEAN필수첫 페이지 여부
lastBOOLEAN필수마지막 페이지 여부

응답 예시 — 성공

JSON
{
  "content": [
    {
      "partnerCorpName": "ABC Corporation",
      "storeId": "store_001",
      "orderId": "ORD-20260301-0001",
      "itemName": "Premium Subscription",
      "serviceName": "ABC Service",
      "orderCountryCode": "KR",
      "orderCurrencyCode": "USD",
      "orderAmount": 50000,
      "createdAt": "2026-03-01T10:00:00Z",
      "transactionId": "txn_abc123def456",
      "blockchainTxId": "0xabcdef1234567890abcdef1234567890abcdef12",
      "paymentType": "PURCHASE",
      "originTransactionId": null,
      "status": "CONFIRMED",
      "finalizedAt": "2026-03-01T10:01:30Z",
      "capturedAt": "2026-03-01T10:01:25Z",
      "failType": null,
      "payCurrencyCode": "USDT",
      "payAmount": 10.87,
      "paymentExchangeRate": 1.0,
      "buyerWalletAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "variableFeeRate": 1.5,
      "settlementId": "stl_xyz789",
      "settlementCurrencyCode": "USDT",
      "settlementExchangeRate": 1.0
    }
  ],
  "totalElements": 1,
  "totalPages": 1,
  "pageNumber": 0,
  "first": true,
  "last": true
}

응답 예시 — 실패

JSON
{
  "code": "PAYMENT_INVALID_REQUEST",
  "message": "Date range must not exceed 90 days"
}

오류 타입 코드

HTTP 상태 오류 코드 설명
400 BAD_REQUEST 필수 파라미터 누락 또는 타입 불일치
404 NOT_FOUND 파트너 정보를 찾을 수 없음
406 PAYMENT_INVALID_REQUEST 유효하지 않은 요청 (날짜 형식 오류, 필수 조건 미충족, 90일 범위 초과 등)
500 INTERNAL_SERVER_ERROR 서버 내부 오류

3. 테스트 가이드

Preview 환경에서 Unifi Pay 결제 연동을 테스트하는 방법입니다.

  1. 1 Unifi Pay 테스트는 Preview 환경에서 진행할 수 있습니다.
  2. 2 Unifi Wallet은 Preview 환경에서 Production 기준의 Google 계정으로 생성 및 연동을 진행합니다. (Preview 환경에서 생성한 Unifi Wallet은 Production 환경과 별도로 관리됩니다.) Preview Unifi Wallet →
  3. 3 Preview 환경의 결제는 Kaia Blockchain의 테스트넷 환경인 Kairos 기준으로 진행됩니다.
  4. 4 아래 가이드를 참고하여 Kairos 테스트넷에서 테스트용 USDT를 확보한 후 결제 테스트를 진행해주시기 바랍니다.
PREVIEW (Kairos Testnet) Unifi Wallet 생성 Preview 환경의 Unifi Wallet 생성 및 연동 STEP 1 테스트 USDT 확보 Kaia Faucet에서 Kairos USDT 수령 STEP 2 결제 테스트 진행 Preview 환경에서 API 연동 테스트 STEP 3

Preview 환경

Kairos Testnet (테스트넷)

Testnet

Preview 환경에서는 카이아 블록체인의 테스트넷인 Kairos 체인이 연동되며, 테스트 자금은 아래 Faucet 서비스를 통해 확보할 수 있습니다.

Kaia Faucet →
Base URL https://app-api-pay.unifi.me