API 레퍼런스: 송금과 송금 링크
대금을 지급하는 메서드예요. 송금은 앱 잔액에서 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_id | integer | user_id / username 중 정확히 하나 | 받는 사람의 Telegram 사용자 ID. 이미 앱에 가입한 사람이어야 해요 |
username | string | user_id / username 중 정확히 하나 | 받는 사람의 사용자명. @는 생략할 수 있어요. 가입하지 않은 사용자명이면 대기 중인 지급이 만들어져요 |
asset | string | 예 | 자산 코드 |
amount | string | 예 | 양수 소수점 문자열. 플랫폼이 정한 건별 최소·최대 금액 범위 안이어야 해요(현재 시세로 환산한 미국 달러 추정치 기준) |
spend_id | string | 예 | 멱등키, 1~64자, 지급 건마다 달라야 해요 |
comment | string | 아니요 | 1024자까지, 받는 사람에게 보여요 |
disable_send_notification | boolean | 아니요 | 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로 옮겨 가요). 송금과 같은 금액 한도와 일일 지급 한도가 적용돼요.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
asset | string | 예 | 자산 코드 |
amount | string | recipients가 없으면 필수 | 양수 소수점 문자열. recipients를 쓰면 명단에서 총액을 계산해요 |
pin_to_user_id | integer | 아니요 | 이 Telegram 사용자 ID만 받아 갈 수 있어요 |
pin_to_username | string | 아니요 | 이 @username만 받아 갈 수 있어요(@는 붙여도 되고 안 붙여도 돼요. pin_to_user_id도 함께 넣으면 무시돼요). 앱을 쓰고 있는 사람의 username이어야 해요 |
spend_id | string | 아니요 | 멱등키(확장 기능) — 하나 넣어 주세요 |
recipients | array | 아니요 | 확장 기능: 1~100개 항목. 각 항목에는 user_id 또는 username과 양수 소수점 문자열 amount가 있어야 해요. 단일 수신자 지정과 함께 쓸 수 없어요 |
password | string | 아니요 | 확장 기능: 받을 때 필요한 비밀번호, 최대 64자 |
expires_in | integer | 아니요 | 확장 기능: 유효 기간(초). 생략하거나 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, …]}를 최신순으로 돌려줘요. 지운 송금 링크는 나오지 않아요.
이 문서가 도움이 됐나요?
의견 고마워요.