인증
실시간 지급대행 API는 Basic 인증을 헤더로 사용하고, 요청 Body를 SIGNATURE 또는 ENCRYPTION 인증 방식으로 더 높은 토스페이먼츠 API 보안 모드를 적용합니다.
•
SIGNATURE: JWS(JSON Web Signature)를 이용한 body 서명
•
ENCRYPTION: JWE(JSON Web Encryption)를 이용한 body 암호화
토스페이먼츠 API 보안 모드의 서명 및 암호화는 토스페이먼츠에서 발급하는 보안키(securityKey)를 사용해요. 가맹점과 토스페이먼츠는 동일한 보안키를 사용합니다. 토스페이먼츠 API 보안 모드를 사용할 때는 TossPayments-api-security-mode 헤더로 인증 방식을 지정해주세요. 헤더를 사용하면 응답도 선택한 보안 모드로 서명 또는 암호화되어 돌아옵니다.
실시간 지급대행 요청 POST API에는 SIGNATURE 또는 ENCRYPTION 인증을 필수로 적용해야 돼요. 기타 GET API에는 선택적으로 적용할 수 있어요.
보안키란?
보안키는 SIGNATURE, ENCRYPTION 방식에서 요청 Body를 서명하거나 암호화할 때 사용하는 키입니다.
•
보안키는 256bit의 HEXENCODED 문자열(string)입니다.
•
보안키가 외부에 노출되지 않도록 주의해주세요.
A. SIGNATURE 방식
1.
{
"amount": 500,
"bank": "신한",
"customerName": "박토스",
"orderId": "test_order_116",
"orderName": "토스 티셔츠 외 2건"
}
JSON
복사
2.
보안키(securityKey)를 이용해서 Request Body 파라미터를 JWS 서명하세요.
•
JWS 헤더의 알고리즘 값을 HS256으로 설정하세요.
•
JWS 헤더의 iat 값을 Request Body를 만든 시간으로 설정하세요. yyyy-MM-dd'T'HH:mm:ss±hh:mm ISO 8601 형식입니다.
•
/**
* @param target target object for signing (requestBody)
* @param securityKey symmetric key from tosspayments
* @return requestBody in JWS
*/
fun sign(target: Any, securityKey: String): String {
val payload = objectMapper.writeValueAsString(target)
val jwsHeader = JWSHeader.Builder(JWSAlgorithm.HS256)
.customParam("iat", OffsetDateTime.now(ZoneId.of("Asia/Seoul")).toString())
.customParam("nonce", UUID.randomUUID().toString())
.build()
val jwsObject = JWSObject(jwsHeader, Payload(payload))
val signer = MACSigner(securityKey)
jwsObject.sign(signer)
return jwsObject.serialize()
}
Kotlin
복사
3.
JWS로 서명한 Request Body를 API 요청의 데이터 값으로 넣고 TossPayments-api-security-mode: SIGNATURE 헤더를 추가하세요.. Basic 인증도 반드시 해주세요.
curl --location 'https://api-dev.tosspayments.com/v1/virtual-accounts' \
--header 'Authorization: Basic dGVzdF9za19aMFJuWVgydzUzMk5vdkJaN2tOM05leXFBcFFFOgo=' \
--header 'Content-Type: text/plain' \
--header 'TossPayments-api-security-mode: SIGNATURE'
--data 'eyJpYXQiOiIyMDIzLTExLTI3VDE4OjA4OjE5LjUzNTA0NyswOTowMCIsIm5vbmNlIjoiZTQ2YTBlNzgtNzZjYy00OGJlLWE0OTItODcwZTJmODAxMTNlIiwiYWxnIjoiSFMyNTYifQ.eyJhbW91bnQiOjUwMCwiYmFuayI6IuyLoO2VnCIsImN1c3RvbWVyTmFtZSI6Iuuwle2GoOyKpCIsIm9yZGVySWQiOiJ0ZXN0X29yZGVyXzExOSIsIm9yZGVyTmFtZSI6Iu2GoOyKpCDti7DshZTsuKAg7Jm4IDLqsbQifQ.U9FzvHYlEMqBgwe-7UfaX2-qsgEOlgkOB98MqEpu_hg'
Bash
복사
4.
응답으로 JWS로 서명한 응답을 받습니다.
eyJpYXQiOiIyMDIzLTExLTI3VDE4OjA4OjMzLjMyNTEzMSswOTowMCIsIm5vbmNlIjoiMWQ3Y2E4MjItZDM3Zi00ZTMyLTkyM2YtZDIyNWI5OTFlNWI2IiwiYWxnIjoiSFMyNTYifQ.eyJtSWQiOiJ0dml2YXJlcHVibGljYSIsImxhc3RUcmFuc2FjdGlvbktleSI6IkY5OUVBODNDMjI5NTM4NjdGNzdFNkEzMDAyODM3RUFEIiwicGF5bWVudEtleSI6IjAxT0F2MlA2eXFMbERKYVluZ3JvendKa0F5anpvWFZlekdkUnBYeEtON0JRTUVrNCIsIm9yZGVySWQiOiJ0ZXN0X29yZGVyXzExOSIsIm9yZGVyTmFtZSI6Iu2GoOyKpCDti7DshZTsuKAg7Jm4IDLqsbQiLCJ0YXhFeGVtcHRpb25BbW91bnQiOjAsInN0YXR1cyI6IldBSVRJTkdfRk9SX0RFUE9TSVQiLCJyZXF1ZXN0ZWRBdCI6IjIwMjMtMTEtMjdUMTg6MDg6MjYrMDk6MDAiLCJhcHByb3ZlZEF0IjpudWxsLCJ1c2VFc2Nyb3ciOmZhbHNlLCJjdWx0dXJlRXhwZW5zZSI6ZmFsc2UsImNhcmQiOm51bGwsInZpcnR1YWxBY2NvdW50Ijp7ImFjY291bnROdW1iZXIiOiJYMzc5MDEwODg3MzI2MiIsImFjY291bnRUeXBlIjoi7J2867CYIiwiYmFua0NvZGUiOiI4OCIsImN1c3RvbWVyTmFtZSI6Iuuwle2GoOyKpCIsImR1ZURhdGUiOiIyMDIzLTEyLTA0VDE4OjA4OjI2KzA5OjAwIiwiZXhwaXJlZCI6ZmFsc2UsInNldHRsZW1lbnRTdGF0dXMiOiJJTkNPTVBMRVRFRCIsInJlZnVuZFN0YXR1cyI6Ik5PTkUiLCJyZWZ1bmRSZWNlaXZlQWNjb3VudCI6bnVsbH0sInRyYW5zZmVyIjpudWxsLCJtb2JpbGVQaG9uZSI6bnVsbCwiZ2lmdENlcnRpZmljYXRlIjpudWxsLCJjYXNoUmVjZWlwdCI6bnVsbCwiY2FzaFJlY2VpcHRzIjpudWxsLCJkaXNjb3VudCI6bnVsbCwiY2FuY2VscyI6bnVsbCwic2VjcmV0IjoicHNfMjR4TGVhNXpWQWd3am5QTUE0NzhRQU1ZTndXNiIsInR5cGUiOiJOT1JNQUwiLCJlYXN5UGF5IjpudWxsLCJjb3VudHJ5IjoiS1IiLCJmYWlsdXJlIjpudWxsLCJpc1BhcnRpYWxDYW5jZWxhYmxlIjp0cnVlLCJyZWNlaXB0Ijp7InVybCI6Imh0dHBzOi8vcGd3ZWIudG9zc3BheW1lbnRzLmNvbTo3MDg2L01wRmxvd0N0cmw_ZXZlbnREaXYxPXNlYXJjaCZldmVudERpdjI9Z2V0Q2FzUmVjZWlwdExpc3QmdHJ4aWQ9dHZpdmEyMDIzMTEyNzE4MDgzMW51Nmg5JlNZU1RFTT1ORVcifSwiY2hlY2tvdXQiOnsidXJsIjoiaHR0cDovL2xvY2FsaG9zdDoxMDUwMS92MS9wYXltZW50cy8wMU9BdjJQNnlxTGxESmFZbmdyb3p3SmtBeWp6b1hWZXpHZFJwWHhLTjdCUU1FazQvY2hlY2tvdXQifSwiY3VycmVuY3kiOiJLUlciLCJ0b3RhbEFtb3VudCI6NTAwLCJiYWxhbmNlQW1vdW50Ijo1MDAsInN1cHBsaWVkQW1vdW50Ijo0NTUsInZhdCI6NDUsInRheEZyZWVBbW91bnQiOjAsIm1ldGhvZCI6IuqwgOyDgeqzhOyijCIsInZlcnNpb24iOiIyMDIyLTExLTE2In0.O-jD5nCUQGMGYtlJ98ccwNnl2rNEc8HbhrVGEHTcP1A
Kotlin
복사
5.
응답 서명을 확인하고 결과 값을 확인하세요.
/**
* @param signedTarget verify target (signed responseBody from tosspayments)
* @param securityKey symmetric key from tosspayments
* @return JWS payload (plain responseBody in JSON)
*/
fun verify(signedTarget: String, securityKey: String): String {
val jwsObject = JWSObject.parse(signedTarget)
val verifier = MACVerifier(securityKey)
jwsObject.verify(verifier)
val verifiedJwsObject = if (jwsObject.state == JWSObject.State.VERIFIED) {
jwsObject
} else {
throw JOSEException("Failed to verify")
}
return verifiedJwsObject.payload.toString()
}
Kotlin
복사
B. ENCRYPTION 방식
요청 body를 JWE로 암호화하는 방법을 가상계좌 발급 API의 예시로 자세히 알아볼게요. 아래 코드는 Nimbus JOSE + JWT 라이브러리로 JWE 암호화・복호화를 합니다.
1.
{
"amount": 500,
"bank": "신한",
"customerName": "박토스",
"orderId": "test_order_117",
"orderName": "토스 티셔츠 외 2건"
}
JSON
복사
2.
Request Body 파라미터를 보안키(securityKey)로 암호화하세요.
•
AES256-GCM 방식을 사용하기 때문에 JWE 헤더의 enc 값을 “A256GCM” 으로 설정하세요({"enc":"A256GCM","alg":"dir","iat": "2023-11-23T21:52:13.378367+09:00", nonce: "{NONCE}"}).
•
JWE 헤더의 iat 값을 Request Body를 만든 시간으로 설정하세요. yyyy-MM-dd'T'HH:mm:ss±hh:mm ISO 8601 형식입니다.
•
/**
* @param target target object for encryption (requestBody)
* @param securityKey symmetric key from tosspayments
* @return requestBody in JWE
*/
fun encrypt(target: Any, securityKey: String): String {
val payload = objectMapper.writeValueAsString(target)
val jweHeader = JWEHeader.Builder(JWEAlgorithm.DIR, EncryptionMethod.A256GCM)
.customParam("iat", OffsetDateTime.now(ZoneId.of("Asia/Seoul")).toString())
.customParam("nonce", UUID.randomUUID().toString())
.build()
val jweObject = JWEObject(jweHeader, Payload(payload))
val key = Hex.decode(securityKey)
jweObject.encrypt(DirectEncrypter(key))
return jweObject.serialize()
}
Kotlin
복사
3.
JWE로 암호화한 Request Body를 API 요청의 데이터 값으로 넣고 TossPayments-api-security-mode: ENCRYPTION 헤더를 추가하세요. Basic 인증도 반드시 해주세요.
curl --location 'https://api-dev.tosspayments.com/v1/virtual-accounts' \
--header 'Authorization: Basic dGVzdF9za19aMFJuWVgydzUzMk5vdkJaN2tOM05leXFBcFFFOgo=' \
--header 'Content-Type: text/plain' \
--header 'TossPayments-api-security-mode: ENCRYPTION'
--data 'eyJlbmMiOiJBMjU2R0NNIiwiaWF0IjoiMjAyMy0xMS0yN1QxODoxMDoyNy44NzU1MzIrMDk6MDAiLCJub25jZSI6IjA4Yzg1YmY5LWNiNWMtNDBiOC1hNzgxLTIwNWVlN2JmNTgyMCIsImFsZyI6ImRpciJ9..70bpqSq2wa3eC1-1.k1uUNAmEJBPsxFtujdbVg84FoBrVny6yJW6fwNaJbAZ_L_IVU7vR6iYdo3ujcJYTmmNY4YRyLdTmeukYMu48QREdTEiyFsRKYP7CRiucc6tjl8_jIOQ-QKNgh-5jyZa1X5Tu-Cu40n6eylKxWx2oNBF8o2tZQ1RSZUEZhg.ntx-qP2bt7g2JkfrvLbWnA'
Bash
복사
4.
응답도 같은 방식으로 암호화되어 반환됩니다.
eyJlbmMiOiJBMjU2R0NNIiwiaWF0IjoiMjAyMy0xMS0yN1QxODoxMDozOC45NDY1MTMrMDk6MDAiLCJub25jZSI6IjIxNDA1ZjdlLWJiNTctNGQwYS04YWQ5LWI5OWY3MzU3MTEwMiIsImFsZyI6ImRpciJ9..YePTUVJyNBU3YcxI.RwSc28MLtUWt9v2rcCnfIJuHDPTYUHFgVvoa5ZnEXsIq_Sv5wH-70mGqa6CZp8xpy-yOSsdeFYqbNv4JZ1wKSNZcbhK4l030QEk6H-uLPkdRPh8xRgXJ5o9LC6UpUkVFNUbtzzsZWB0XECGbSBtn_gg-eTLGL8LZT02JrP5Y79sN8ooE-4zyvBaEL3FZFcTWuDrCm565s2g84jes4q0Sr3o3HnW3nJ7nJiXFBCrQdlmFYeWrWEJZucFmb_0KxBAWVMOSQBQ6lMEDpomImpgGZwjhSz_zj-W09HICb3Nhp4Hx0hha8iTMIVyF4vIn6rdh9n_A-SVB5tN0qwcQB33MJ4rZfC1-ycKIDqDNQcnNMcrPfMwFsb3KECpKKOudH5yf5EveKwWEJul_-njs1OLyumYKGKj20fn1QE_twSFiWpfOfxsDzizXh5TetgO-c2PSjSQ2ksi-k05sNATQrxwjqXtS6KH01qig6QL7xVHhj34eEy6QU-67k80PUsZK2BXNhy__Daw0LGuMMpadQY2d7O-zAKjb4m6SVEpXuqKf-dOvX7H4Y5d0zuZGJZ21AG2Y2HmE-J-G4fzAKcbV41QaZQswgyz64uEtqTqeD4TkDYvUEr0AqMLcZc71iwBxUcEiQ6UQCPgytBhjBSgzxITeZ0GS6RUZ-tbhIGDwE1LbsMglqdXuNDu4ASUzOpeCzGnEHLcU0nGWD_a4ymWOQxYbmBjQ3j6Lb3UlkkaRBKrjIwvLBfB60J4ZZtWkLugo0dY4iWik0r1-AGKT3yJOEgE_PjebFTJ7mznRWzOD_ORpGKDhOMz12Y6UE8Kfvoss33D--8scEm03U6GvSspM7S7WD_juHqpQmFdTPAPx28OqxllDq94lE9g81pX6WeqcmdDNpgy6pZCpMCmQPKQH3lkeRaGEHiFsSPrJNNWO7EkvOcdhj9uyGGtQilTHsXbupruchQzQNKfDsGC2aQdLhCaC20atsbRpry-739W0WRqnIFZ8_2W4aZIRXpkygpaZ5vUTyq_xpp5BjV_vt5-NdOSkpZSvU79HroOR0-oCjddixO6AuBpFuQtVz8J6ajBfUUFFVD91GWzj3beqAKtWQkk0Een8c-f57FMJ9o1bmqtwVVAwV8BfAYLBBUdYKIBYfwPlvog_2B_OAMKgXEQOyD9EnTsk9uZlRbWt7-ofICtslhNB1f_V0-sRQQ7nzs8cv51fvSX0lrflvnhq8KJNHFmX0KKIYb1kpP66ld9m7sLlNvXYnjZog6FaH40evekW4hehiHCFnFF25_NSfIgmGcISmskO-m3d2fk1j3UwS-CgkEsSKaz0xxKcqjPhy2fT3Ec63OLwCpuP0ePBX3HSDKwQlSVmVz1TFU_aTimo81ufGKKfiNEXrv42SomNiXbSVPELu5tLQOyVnDrvUha31fiarHzNL9mfhqsemo3-hj6VKk6YQspM8d8ldzFVVyxekUGLRIxeaJKoStIu-2R7FrjTVgfPweDKw1RrfAoazTen9wKGcCC66XiARIpZ0sg6qjGRs-TQgLRO2eeYfrVlspevwoABFTnhzL9wQqhQySm_M2Chkn6u21ElJjlw1pHaoqABeky0LG3uolUUUYbPmbDyz5lUrDXwrCYYvP1M_iQn2Qcua5InQsIkGfnUtgwotSTXhqpwJw3qetAcKXgM0H78bE4Cr57mN_UR7yGat8NIkD79PIvkrA4F04x9JmsSCVcvlLW-FmGaNuUmziPXb6E.nwY-rgvJMEnkGvdqJqC8KA
JSON
복사
5.
응답을 복호화하고 결과 값을 확인하세요.
/**
* @param encryptedTarget decrypt target (responseBody from tosspayments)
* @param securityKey symmetric key from tosspayments
* @return JWE payload (plain responseBody in JSON)
*/
fun decrypt(encryptedTarget: String, securityKey: String): String {
val jweObject = JWEObject.parse(encryptedTarget)
val key = Hex.decode(securityKey)
jweObject.decrypt(DirectDecrypter(key))
val decryptedJweObject = if (jweObject.state == JWEObject.State.DECRYPTED) {
jweObject
} else {
throw JOSEException("Failed to decrypt")
}
return decryptedJweObject.payload.toString()
}
Kotlin
복사
TransferDelegationAccount 객체
가맹점의 지급 계좌 정보입니다.
transferDelegationAccountKey string
지급 계좌 키입니다.
balanceAmount number
지급 계좌의 금액입니다. 서브몰에 지급이 가능한 잔액입니다.
currency string
통화입니다.
virtualAccounts array
지급 계좌 정보입니다.
잔액 조회
GET /v1/transfer-delegation-accounts
요청
curl --request GET \
--url https://api.tosspayments.com/v1/transfer-delegation-accounts \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg=='
Bash
복사
응답
잔액 조회에 성공했다면 TransferDelegationAccount 객체가 돌아옵니다.
[
{
"transferDelegationAccountKey": "TDA_PQLMmf2l",
"balanceAmount": 10000000,
"currency": "KRW",
"virtualAccounts": [{
"bankCode": "020",
"accountNumber": "94000910518216",
"holderName": "김토스 상점"
}],
}
]
Bash
복사
TransferDelegationSubMall 객체
가맹점이 등록한 서브몰 정보입니다.
subMallId string
서브몰의 ID입니다. 최대 길이는 20자입니다.
type string
서브몰의 타입입니다. CORPORATE(법인), INDIVIDUAL(개인) 중 하나입니다.
companyName nullable · string
서브몰의 상호명입니다. 최대 길이는 공백을 포함한 한글 30자, 영문 60자입니다. 서브몰의 type이 CORPORATE(법인)일 때만 사용됩니다.
representativeName nullable · string
서브몰의 대표자명입니다. 최대 길이는 40자입니다. 서브몰의 type이 CORPORATE(법인)일 때만 사용됩니다.
businessNumber nullable · string
서브몰의 사업자등록번호 입니다. 길이는 10자입니다. 서브몰의 type이 CORPORATE(법인)일 때만 사용됩니다.
account object
서브몰에서 정산 금액을 지급받을 계좌 정보를 담은 객체입니다.
email nullable · string
서브몰 이메일 주소입니다.
phoneNumber nullable · string
서브몰 연락처입니다. - 없이 숫자만 넣어야 합니다. 길이는 8자 이상 11자 이하여야 합니다.
metadata nullable · object
서브몰과 관련된 추가 정보를 key-value 쌍으로 담고 있는 객체입니다. 최대 50개의 key-value 쌍을 포함할 수 있으며 전체 크기는 4kB 이하입니다.
서브몰 등록
지급 계좌의 유효성을 검증하고 요청한 정보를 서브몰로 등록합니다.
[POST] /v1/transfer-delegation-sub-malls
Request Body 파라미터
subMallId 필수 · string
서브몰의 ID입니다. 최대 길이는 20자입니다.
type 필수 · string
서브몰의 타입입니다. CORPORATE(법인), INDIVIDUAL(개인) 중 하나의 값을 넣어주세요.
companyName string
서브몰의 상호명입니다. 서브몰의 type이 CORPORATE일 때 필수로 보내야 하는 파라미터입니다. 최대 길이는 공백을 포함한 한글 30자, 영문 60자입니다.
representativeName string
서브몰의 대표자명입니다. 최대 길이는 40자입니다. 서브몰의 type이 CORPORATE(법인)일 때만 사용됩니다.
businessNumber string
서브몰의 사업자등록번호 입니다. 서브몰의 type이 CORPORATE일 때 필수로 보내야 하는 파라미터입니다. 길이는 10자입니다.
account 필수 · string
서브몰에서 정산 금액을 지급받을 계좌 정보를 담은 객체입니다.
email 필수 · string
서브몰 이메일 주소입니다.
phoneNumber 필수 · string
서브몰 연락처입니다. - 없이 숫자만 넣어야 합니다. 길이는 8자 이상 11자 이하여야 합니다.
metadata object
서브몰과 관련된 추가 정보를 key-value 쌍으로 담고 있는 JSON 객체입니다. 최대 50개의 key-value 쌍을 포함할 수 있으며 전체 크기는 4kB 이하입니다.
요청
curl --request POST \
--url https://api.tosspayments.com/v1/transfer-delegation-sub-malls \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg==' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 9c57d3e3-8d96-4e6a-9fd9-5434091eb173' \
--data '{"subMallId":"testmall100","account":{"bank":"03","accountNumber":"34000000000011","holderName":"김토페"},"type":"CORPORATE","email":"example@email.com","phoneNumber":"01012341234","companyName":"테스트몰100","representativeName":"김토페","businessNumber":"1200220000", "metadata": {"key1": "value1","key2": "value2"}}'
Bash
복사
응답
서브몰 등록에 성공했다면 TransferDelegationSubMall 객체가 돌아옵니다.
{
"subMallId": "testmall100",
"type": "CORPORATE",
"companyName": "테스트몰100",
"representativeName": "김토페",
"businessNumber": "1200220000",
"account": {
"bankCode": "003",
"accountNumber": "00123412341234",
"holderName": "김토페"
},
"email": "testmall100@test.com",
"phoneNumber": "01012341234",
"metadata": {
"key1": "value1",
"key2": "value2"
}
}
JSON
복사
서브몰 수정
등록된 서브몰의 정보를 수정합니다. 서브몰이 삭제되지 않은 상태에서만 수정이 가능합니다. 서브몰 ID를 제외한 모든 정보를 수정할 수 있어요.
[POST] /v1/transfer-delegation-sub-malls/{subMallId}
Path 파리미터
subMallId 필수 · string
서브몰 ID입니다.
Request Body 파라미터
companyName string
서브몰의 상호명입니다. 서브몰의 type이 CORPORATE일 때 필수로 보내야 하는 파라미터입니다. 최대 길이는 공백을 포함한 한글 30자, 영문 60자입니다.
representativeName string
서브몰의 대표자명입니다. 최대 길이는 40자입니다. 서브몰의 type이 CORPORATE(법인)일 때만 사용됩니다.
businessNumber string
서브몰의 사업자등록번호 입니다. 서브몰의 type이 CORPORATE일 때 필수로 보내야 하는 파라미터입니다. 길이는 10자입니다.
account 필수 · string
서브몰에서 정산 금액을 지급받을 계좌 정보를 담은 객체입니다.
email string
서브몰 이메일 주소입니다.
phoneNumber string
서브몰 연락처입니다. - 없이 숫자만 넣어야 합니다. 길이는 8자 이상 11자 이하여야 합니다.
metadata object
서브몰과 관련된 추가 정보를 key-value 쌍으로 담고 있는 객체입니다. 최대 50개의 key-value 쌍을 포함할 수 있으며 전체 크기는 4kB 이하입니다.
요청
curl --request POST \
--url https://api.tosspayments.com/v1/transfer-delegation-sub-malls/{subMallId} \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg==' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 6f873db5-8bfb-4d30-9b07-4cc7d4fba7f9' \
--data '{"account":{"bank":"003","accountNumber":"34000000000011","holderName":"김토페"},"companyName":"테스트몰200","representativeName":"김토페","businessNumber":"1200220000"}'
Bash
복사
응답
서브몰 수정에 성공했다면 TransferDelegationSubMall 객체가 돌아옵니다.
{
"subMallId": "testmall100",
"type": "CORPORATE",
"companyName": "테스트몰200",
"representativeName": "김토페",
"businessNumber": "1200220000",
"account": {
"bankCode": "003",
"accountNumber": "34000000000011",
"holderName": "김토페"
},
"email": "testmall100@test.com",
"phoneNumber": "01012341234",
"metadata": null
}
JSON
복사
서브몰 삭제
등록된 서브몰을 삭제합니다. 삭제한 서브몰 ID는 다시 사용할 수 없어요.
[POST] /v1/transfer-delegation-sub-malls/{subMallId}/delete
요청
curl --request POST \
--url https://api.tosspayments.com/v1/transfer-delegation-sub-malls/{subMallId}/delete \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg==' \
Bash
복사
응답
서브몰 삭제에 성공했다면 HTTP 200 상태 코드와 empty body가 돌아옵니다.
서브몰 조회
등록된 서브몰을 조회합니다. 삭제되지 않은 서브몰만 조회할 수 있어요.
[GET] /v1/transfer-delegation-sub-malls/{subMallId}
요청
curl --request GET \
--url https://api.tosspayments.com/v1/transfer-delegation-sub-malls/{subMallId} \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg=='
Bash
복사
응답
서브몰 조회에 성공했다면 TransferDelegationSubMall 객체가 돌아옵니다.
{
"subMallId": "testmall100",
"type": "CORPORATE",
"companyName": "테스트몰200",
"representativeName": "김토페",
"businessNumber": "1200220000",
"account": {
"bankCode": "003",
"accountNumber": "34000000000011",
"holderName": "김토페"
},
"email": "testmall100@test.com",
"phoneNumber": "01012341234",
"metadata": null
}
JSON
복사
TransferDelegation 객체
실시간 지급대행 요청
지급 대상 서브몰에게 지급 금액을 요청 직후 이체합니다. 요청 시점에 잔액이 부족하면 요청이 실패합니다.
[POST] /v1/transfer-delegations/instant
TossPayments-api-security-mode 를 필수로 적용하세요. SIGNATURE 또는 ENCRYPTION 방식을 사용하세요.
Request Body 파라미터
subMallId 필수 · string
서브몰의 ID입니다. 최대 길이는 20자입니다.
transferAmount 필수 · number
정산할 지급 금액입니다.
metadata object
서브몰과 관련된 추가 정보를 key-value 쌍으로 담고 있는 객체입니다. 최대 50개의 key-value 쌍을 포함할 수 있으며 전체 크기는 4kB 이하여야 합니다. key와 value 모두 문자열 형식이어야 합니다.
transferSummary string
지급대행으로 입금된 금액의 세부 내용(적요)입니다. 서브몰 통장에 표기됩니다. 최대 길이는 7자입니다.
실시간 지급대행 에러 목록
실시간 지급대행 API에서 발생할 수 있는 에러는 다음과 같습니다.
에러 코드 | 한글 메시지 | 원인 |
UNAUTHORIZED_SECURITY_KEY | 인증되지 않은 보안 키 입니다. | 토스페이먼츠에서 발급하지 않은 보안 키로 서명/암호화를 시도했습니다. |
EXPIRED_REQUEST | iat 값이 만료된 요청입니다. | iat 값이 만료됐습니다. |
FORBIDDEN_CONSECUTIVE_REQUEST | 반복적인 요청은 허용되지 않습니다. 잠시 후 다시 시도해주세요. | 같은 nonce 값을 가진 요청이 반복적으로 호출됐습니다. |
INVALID_SECURITY_BODY | 잘못된 JWS/JWE 요청 값입니다. 알고리즘 및 헤더 값을 확인하세요. | 허용되지 않은 알고리즘을 사용했거나 iat, nonce 헤더에 문제가 있습니다. |
INVALID_AUTHORIZE_AUTH | 잘못된 인증 방식입니다. | 잘못된 security mode를 사용했습니다. |
요청
아래 Request Body를 SIGNATURE 또는 ENCRYPTION 방식으로 인증하고 API 요청에 넣어주세요.
[
{
"subMallId": "mall1",
"transferAmount": 50000,
"metadata": null,
"transferSummary": "김토스"
},
{
"subMallId": "mall2",
"transferAmount": 50000,
"metadata": null,
"transferSummary": "김토스"
},
]
JSON
복사
curl --location 'https://api.tosspayments.com/v1/transfer-delegations/instant' \
--header 'TossPayments-Api-Security-Mode: SIGNATURE' \
--header 'Content-Type: text/plain' \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg==' \
--data '{SIGNATURE_MODE_ENCODED_DATA}'
Bash
복사
응답
인코딩된 응답을 확인하세요.
실시간 지급대행에 성공했다면 TransferDelegation 객체가 돌아옵니다.
[
{
"transferDelegationKey": "FPA20231001_000000000001",
"subMallId": "mall1",
"type": "INSTANT",
"transferDate": "2023-10-01",
"transferAmount": 50000,
"requestedAt": "2023-10-01T00:00:00",
"account": null,
"status": "REQUESTED",
"metadata": null,
"failure": null,
"transferSummary": "김토스"
},
{
"transferDelegationKey": "FPA20231001_000000000001",
"subMallId": "mall2",
"type": "INSTANT",
"transferDate": "2023-10-01",
"transferAmount": 50000,
"requestedAt": "2023-10-01T00:00:00",
"account": null,
"status": "REQUESTED",
"metadata": null,
"failure": null,
"transferSummary": "김토스"
}
]
JSON
복사
지급대행 단건 조회
지급 건의 키를 사용해서 1개의 지급 객체를 조회합니다.
[GET] /v1/transfer-delegations/{transferDelegationKey}
요청
curl --request GET \
--url https://api.tosspayments.com/v1/transfer-delegations/{transferDelegationKey} \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg=='
Bash
복사
응답
지급대행 단건 조회에 성공했다면 TransferDelegation 객체가 돌아옵니다.
{
"transferDelegationKey": "FPA20231001_000000000001",
"subMallId": "mall1",
"type": "INSTANT",
"transferDate": "2023-10-01",
"transferAmount": 50000,
"requestedAt": "2023-10-01T00:00:00",
"account": null,
"status": "REQUESTED",
"metadata": null,
"failure": null,
"transferSummary": "김토스"
}
Bash
복사
지급대행 조회
조회 기간 범위에서 모든 지급 건을 조회합니다. 조회 기간에 지급 건이 없으면 빈 배열을 반환합니다.
[GET] /v1/transfer-delegations?startDate={startTransferDate}&endDate={endTransferDate}&cursor={cursor}&limit={limit}
Path 파라미터
startTransferDate 필수 · string
조회를 시작하고 싶은 날짜 정보입니다. ISO 8601 형식인 yyyy-MM-dd를 사용합니다. (e.g. 2022-01-01)
endTransferDate 필수 · string
조회를 마치고 싶은 날짜 정보입니다. yyyy-MM-dd ISO 8601 형식입니다. (e.g. 2022-01-01)
cursor string
특정 지급 건의 transferDelegationKey를 설정하면, 해당 지급 건 이후의 내역만 조회됩니다.
limit integer
한 번에 조회할 지급 건의 수입니다. 생략하면 100 건까지 조회됩니다. 최대값은 10,000 건입니다.
요청
curl --request GET \
--url https://api.tosspayments.com/v1/transfer-delegations?startDate={startTransferDate}&endDate={endTransferDate}&cursor={cursor}&limit={limit} \
--header 'Authorization: Basic dGVzdF9za19hQlg3emsyeWQ4eW9Yd29KMGdxVng5UE9McUtROg=='
Bash
복사
응답
지급대행 조회에 성공했다면 TransferDelegation 객체가 돌아옵니다.
{
"hasNext": false,
"lastCursor": "FPA12345",
"data": [
{
"transferDelegationKey": "FPA20231001_000000000001",
"subMallId": "mall1",
"type": "INSTANT",
"transferDate": "2023-10-01",
"transferAmount": 50000,
"requestedAt": "2023-10-01T00:00:00",
"account": null,
"status": "REQUESTED",
"metadata": null,
"failure": null,
"transferSummary": "김토스"
},
{
"transferDelegationKey": "FPA20231001_000000000001",
"subMallId": "mall2",
"type": "INSTANT",
"transferDate": "2023-10-01",
"transferAmount": 50000,
"requestedAt": "2023-10-01T00:00:00",
"account": null,
"status": "REQUESTED",
"metadata": null,
"failure": null,
"transferSummary": "김토스"
}
]
}
Bash
복사