tgpay cryptoAPI
crypto-payapitransferspayouts

API 레퍼런스: 송금과 송금 링크

읽는 데 5분마지막 수정 2026년 10월 9일

대금을 지급하는 메서드예요. 송금은 앱 잔액에서 Telegram 사용자의 지갑으로 자금을 보내거나, 새로 가입할 받는 사람이 봇을 열 때까지 보관해요. 송금 링크는 미리 돈을 채워 두고 받아 가게 하는 링크예요. 공통 규칙(인증, 응답 형식, 금액, spend_id)은 Merchant API 레퍼런스에 있어요.

돈이 나가는 세 메서드는 모두 앱의 지급 모드를 따라요. 새 앱은 처음부터 누구에게나 지급할 수 있고, 소유자가 범위를 좁혀 뒀다면 목록에 있는 받는 사람에게만 지급되거나(403 recipient_not_allowed) 아예 지급되지 않아요(403 payouts_disabled). 모드는 소유자가 미니 앱에서 정하고, API로는 바꿀 수 없어요. 지급을 무엇에 쓸 수 있는지는 Merchant API 이용약관에 정해져 있어요.

transfer

POST /pay/api/transfer — payouts 권한, 분당 30회. 이미 가입한 사람은 바로 받아요. 가입하지 않은 username으로 보내면 pending 상태의 송금이 만들어져요. 받는 사람이 그 사용자명으로 봇을 처음 열 때까지 자금은 에스크로에 보관돼요. 받지 않은 자산은 30일의 기한(expires_at)이 지나면 앱 잔액으로 돌아와요. 회계에 반영하기 전에 status: "returned"로 반환을 확인하세요. 봇을 한 번도 실행하지 않은 사람에게는 봇이 먼저 메시지를 보낼 수 없으니 invite_url을 직접 전달해 주세요. 최종 상태는 completed 또는 returned예요. transfer_completed와 transfer_returned 웹훅을 구독하거나 getTransfers로 조회하세요.

파라미터타입필수설명
user_idintegeruser_id / username 중 정확히 하나받는 사람의 Telegram 사용자 ID. 이미 앱에 가입한 사람이어야 해요
usernamestringuser_id / username 중 정확히 하나받는 사람의 사용자명. @는 생략할 수 있어요. 가입하지 않은 사용자명이면 대기 중인 지급이 만들어져요
assetstring예자산 코드
amountstring예양수 소수점 문자열. 플랫폼이 정한 건별 최소·최대 금액 범위 안이어야 해요(현재 시세로 환산한 미국 달러 추정치 기준)
spend_idstring예멱등키, 1~64자, 지급 건마다 달라야 해요
commentstring아니요1024자까지, 받는 사람에게 보여요
disable_send_notificationboolean아니요true면 즉시 지급할 때 받는 사람에게 알림을 보내지 않아요. 대기 중이던 송금을 받아 갈 때는 이 설정과 관계없이 알림을 보내요

결과는 송금 객체예요. transfer_id, hash, user_id, recipient_username, asset, amount, amount_minor, spend_id, comment, status(pending / completed / returned), created_at, completed_at, expires_at, invite_url이 들어 있어요. 새로 가입할 받는 사람을 기다리는 동안에는 user_id가 null일 수 있고, 완료 전까지 completed_at은 null이에요.

오류: 403 payouts_disabled / 403 recipient_not_allowed(지급 모드에 걸렸을 때), 404 user_not_found(ID를 찾을 수 없거나 받을 수 없는 사용자일 때), 400 invalid_recipient(받는 사람의 사용자명이 올바르지 않을 때), 400 amount_too_small / 400 amount_too_big(보낼 수 있는 범위를 벗어났을 때), 409 insufficient_funds, 400 unknown_asset, 400 invalid_amount, 그리고 spend_id 관련 오류인 409 idempotency_conflict / 409 idempotency_in_progress.

transferBatch

POST /pay/api/transferBatch — payouts 권한, 분당 10회. 대량 지급용 확장 기능이에요. 한 번에 송금 100건까지 보낼 수 있어요.

파라미터는 items 하나예요. 배열의 각 항목에 transfer의 파라미터를 모두 넣어요(user_id 또는 username, asset, amount, spend_id, 그리고 선택인 comment와 disable_send_notification). 배치 안에서 spend_id는 서로 달라야 하고, 겹치면 아무것도 실행되기 전에 400 duplicate_spend_id로 전체가 실패해요. 항목 구조 오류, 앱의 지급 모드, 일일 한도 때문에도 지급 전에 요청 전체가 거절될 수 있어요. 접수된 요청의 결과는 result.items에 나와요.

항목은 순서대로, 따로따로 처리돼요. 하나가 실패해도 나머지가 되돌려지지 않아요. 일부가 실패해도 호출 자체는 HTTP 200에 ok: true로 돌아오니까, 항목마다 꼭 확인해 주세요.

  • 성공: {"ok": true, "spend_id": "…", "result": <transfer object>}
  • 실패: {"ok": false, "spend_id": "…", "error": {"code": …, "name": "…"}} — 오류 이름은 단건 transfer와 같아요.

배치에 쓴 멱등키는 단건 송금에도 적용돼요. 배치 전체를 다시 보내거나, 항목 하나를 같은 spend_id로 단건 transfer에 다시 보내도 두 번 나가지 않고 원래 결과가 돌아와요.

getTransfers

GET /pay/api/getTransfers — read 권한. 필터: asset, transfer_ids(쉼표로 구분), spend_id(정확히 일치 — 내 키로 지급 건을 찾을 때 써요), status(pending / completed / returned), 그리고 offset / count. {"items": [transfer, …]}를 최신순으로 돌려줘요.

createCheck

POST /pay/api/createCheck — checks 권한, 분당 60회. 기본적으로 앱 잔액으로 일회용 송금 링크를 만들어요. 링크를 가진 사람이면 누구나, 또는 지정한 사람만 자기 지갑으로 받아 갈 수 있어요. recipients 확장 기능으로 받는 사람별 금액이 다른 명단을 만들 수도 있어요. 총액은 만드는 순간 보류돼요(getBalance에서 available에서 onhold로 옮겨 가요). 송금과 같은 금액 한도와 일일 지급 한도가 적용돼요.

파라미터타입필수설명
assetstring예자산 코드
amountstringrecipients가 없으면 필수양수 소수점 문자열. recipients를 쓰면 명단에서 총액을 계산해요
pin_to_user_idinteger아니요이 Telegram 사용자 ID만 받아 갈 수 있어요
pin_to_usernamestring아니요이 @username만 받아 갈 수 있어요(@는 붙여도 되고 안 붙여도 돼요. pin_to_user_id도 함께 넣으면 무시돼요). 앱을 쓰고 있는 사람의 username이어야 해요
spend_idstring아니요멱등키(확장 기능) — 하나 넣어 주세요
recipientsarray아니요확장 기능: 1~100개 항목. 각 항목에는 user_id 또는 username과 양수 소수점 문자열 amount가 있어야 해요. 단일 수신자 지정과 함께 쓸 수 없어요
passwordstring아니요확장 기능: 받을 때 필요한 비밀번호, 최대 64자
expires_ininteger아니요확장 기능: 유효 기간(초). 생략하거나 0이면 만료되지 않아요

결과는 송금 링크 객체예요. check_id, hash, asset, amount, amount_minor, bot_check_url(받아 가는 t.me 링크), status(active / activated), pin_to_user_id, created_at, activated_at, expires_at, recipients가 들어 있어요. 일반 링크의 recipients는 null이고, 명단형 링크는 각 항목에 user_id, username, amount, amount_minor, claimed_at이 있어요. 받을 때마다 선택 구독한 check_activated 웹훅이 발생하며 명단형 수령에는 activated_slot도 포함돼요. 만료되면 미수령 잔액을 반환하며 명단형 만료에는 check_expired가 전송될 수 있어요.

현재 응답은 전부 받지 않은 링크를 만료 여부와 관계없이 status: "active"로 표시해요. expires_at도 확인하고 active만으로 아직 받을 수 있다고 판단하지 마세요.

오류: 403 payouts_disabled / 403 recipient_not_allowed(지급 모드에 걸렸을 때 — allowlist 모드에서는 지정한 사용자나 명단의 모든 수신자가 허용 목록에 있어야 해요), 400 unknown_asset, 400 invalid_amount, 404 user_not_found(지정한 username을 가진 사람이 없을 때), 409 insufficient_funds, 그리고 앞서 설명한 spend_id 관련 오류가 있어요.

deleteCheck

POST /pay/api/deleteCheck — checks 권한. 파라미터는 check_id 하나예요. 활성 송금 링크를 취소하고 아직 받지 않은 나머지 금액을 앱 잔액으로 돌려줘요. true를 돌려줘요. 오류: 404 check_not_found, 409 check_not_active(모두 받았거나 만료·삭제된 경우).

getChecks

GET /pay/api/getChecks — read 권한. 필터: asset, check_ids(쉼표로 구분), status(active / activated), 그리고 offset / count. {"items": [check, …]}를 최신순으로 돌려줘요. 지운 송금 링크는 나오지 않아요.