지급대행
지급대행 기능이 활성화된 PAYSTORY 가맹점은 결제 정산 잔액 안에서 Seller에게 지급을 요청할 수 있습니다. Payout 원장에는 Seller 지급뿐 아니라 매일 남은 잔액을 가맹점 계좌로 보내는 자동 정산도 기록됩니다. 기존 주문별 Settlement는 별도 원장으로 유지됩니다.
모든 API는 가맹점의 secret key 또는 해당 가맹점 운영자 세션으로 호출해야 합니다.
Balance 객체
interface Balance {
pendingAmount: { currency: 'KRW'; value: number }
availableAmount: { currency: 'KRW'; value: number }
}pendingAmount는 정산주기가 지나지 않은 정산 예정액입니다. availableAmount는 Payout 또는 가맹점 정산에 사용할 수 있는 금액입니다. 정산 후 취소가 발생하면 availableAmount.value가 음수일 수 있습니다.
GET /merchants/:mId/balancesSeller
Payout의 destination에는 같은 가맹점에 등록되어 있고 삭제되지 않은 Seller의 id를 사용합니다. 실제 지급을 요청하려면 Seller의 Paystory Seller ID가 등록되어 있어야 합니다.
POST /merchants/:mId/sellers
GET /merchants/:mId/sellers
GET /merchants/:mId/sellers/:sellerId
DELETE /merchants/:mId/sellers/:sellerIdPayout 객체
interface Payout {
id: string
batchId: string
refPayoutId: string
destination:
| { type: 'SELLER'; sellerId: string }
| { type: 'MERCHANT' }
payoutDate: string
amount: {
currency: 'KRW'
value: number
}
requestedAt: string
submittedAt: string | null
statusUpdatedAt: string
lastResultCheckedAt: string | null
completedAt: string | null
status: 'PENDING' | 'SUBMITTING' | 'REQUESTED' | 'COMPLETED' | 'FAILED' | 'CANCELED'
error: { code: string; message: string } | null
reconciliationRequired: boolean
}id: 캔디페이가 발급한 Payout ID입니다.batchId: 같은 bulk 요청으로 예약된 항목들이 공유하는 ID입니다.refPayoutId: 가맹점이 발급하는 최대 50자의 고유 ID입니다. 같은 가맹점에서 다시 사용할 수 없습니다.destination: Seller 지급이면SELLER와 Seller ID, 자동 정산이면MERCHANT입니다. API 요청에서는 Seller만 지정할 수 있습니다.payoutDate: backend가 Paystory 접수 시간과 한국 영업일에 따라 선택한 지급일입니다.error: Provider의 마지막 오류를 안전하게 정규화한 값입니다. 원본 응답이나 계좌 정보는 포함하지 않습니다.reconciliationRequired: 장기 처리 중이거나 마지막 조회 오류가 있어 운영 확인이 필요한 상태입니다.
지급대행 요청
POST /merchants/:mId/payouts한 번에 1건 이상 100건 이하를 요청할 수 있습니다. 모든 항목은 같은 batchId로 예약됩니다.
[
{
"refPayoutId": "merchant-payout-20260813-1",
"destination": "0198f0cc-0d16-7bd2-8f2c-e9064ad0bb0e",
"amount": {
"currency": "KRW",
"value": 10000
}
},
{
"refPayoutId": "merchant-payout-20260813-2",
"destination": "0198f0cc-0d16-7bd2-8f2c-e9064ad0bb0f",
"amount": {
"currency": "KRW",
"value": 25000
}
}
]각 지급액은 1원 이상 10억원 미만의 정수이며 전체 합계가 현재 availableAmount 이하여야 합니다. Seller 소유권, 금액, 잔액, refPayoutId, Provider 지급 슬롯을 한 트랜잭션에서 모두 검증합니다. 하나라도 실패하면 어떤 Payout도 생성되지 않습니다.
검증이 끝나면 모든 항목을 PENDING으로 먼저 기록해 잔액을 예약합니다. 이후 Paystory 제출은 항목별로 비동기 처리됩니다. 한 항목의 실패나 불확실성이 다른 항목 제출을 막지 않습니다. FAILED 또는 CANCELED가 확정된 항목의 금액만 Balance에 자동으로 복원됩니다.
모든 refPayoutId가 같은 기존 batch에 속하고 ref/destination/amount 집합이 완전히 같으면 기존 batch를 반환합니다. 일부 ref만 중복되거나 내용이 달라지면 전체 요청이 DUPLICATE_REF_PAYOUT_ID로 거절됩니다.
Paystory 결과 조회 키는 Seller ID와 지급일입니다. 같은 키를 이미 사용한 요청은 지급일을 자동 변경하지 않고 PAYOUT_PROVIDER_SLOT_CONFLICT로 전체 거절합니다.
응답은 다음 목록 객체입니다.
interface PayoutList {
hasMore: boolean
size: number
nextCursor: string | null
items: Payout[]
}단건 조회
GET /merchants/:mId/payouts/:payoutId해당 가맹점의 Payout 객체를 반환합니다.
목록 조회
GET /merchants/:mId/payouts?limit=10&startingAfter={payoutId}&payoutDateGte=2026-08-01&payoutDateLte=2026-08-31limit: 기본값 10, 최대 10,000입니다.startingAfter: 직전 응답의nextCursor입니다.payoutDateGte,payoutDateLte:YYYY-MM-DD형식의 지급일 범위입니다.
목록 응답은 hasMore, size, nextCursor, items를 반환합니다.
상태 모델
PENDING: 로컬 예약 완료, Provider 제출 대기SUBMITTING: Provider 호출을 시작했으나 접수 여부가 불확실할 수 있음REQUESTED: Paystory 접수 완료COMPLETED: 지급 완료FAILED: 요청 또는 지급 실패 확정CANCELED: Paystory에서 취소 확정
SUBMITTING 상태에서 응답이 유실되면 같은 요청을 다시 전송하지 않고 주기적인 결과 조회로 상태를 확인합니다. 조회 네트워크 오류나 응답 불일치만으로 지급을 실패 처리하지 않으므로, 이때는 잔액 차감도 유지됩니다.
사용자가 Payout을 취소하는 공개 API는 제공하지 않습니다. Paystory에서 외부적으로 취소된 결과는 주기적인 조회 후 CANCELED로 반영됩니다.