Merchant API 레퍼런스
모든 메서드가 함께 쓰는 규칙과, 읽기 전용 조회 메서드예요. 메서드별 문서는 청구서와 환불, 송금과 송금 링크, 구독, webhook에 있어요.
이 API는 Crypto Bot과 호환돼요. 이미 Crypto Bot으로 붙여 둔 연동이라면 기본 URL과 토큰만 바꾸면 돌아가요. 그 규격을 넘어서는 것은 아래에서 확장 기능이라고 표시해 뒀어요.
메서드와 객체, 오류 이름, webhook까지 전부 담은 OpenAPI 3.1 명세도 이 문서 옆에 같이 두었어요. crypto-pay-openapi.yaml · crypto-pay-openapi.json. 코드 생성기나 API 클라이언트, AI 도구에 그대로 넣어 쓰면 돼요.
기본 URL과 인증
모든 메서드는 https://app.tgpaycrypto.com/pay/api/<methodName>에 있어요.
요청마다 TgPayCrypto-API-Token 헤더에 토큰을 담아 인증해요
(Crypto-Pay-API-Token도 호환용 별칭으로 받아 주고, 둘 다 보내면 원래 헤더가
이겨요). 토큰이 없거나 잘못됐거나 폐기됐을 때, 그리고 지운 앱의 토큰일 때는
401 unauthorized가 돌아와요.
토큰은 <app_id>:<secret> 모양이고, 만들거나 새로 발급할 때 한 번만 보여
줘요. 서버에는 해시만 남아요.
개발자로 시작하기를 보세요.
토큰과 권한
인증하는 방식이 똑같은 두 가지 열쇠가 있어요.
- 기본 토큰 — 모든 메서드를 쓸 수 있고, webhook에 서명하는 유일한 열쇠예요.
- 권한 제한 토큰(확장 기능) — 앱마다 최대 10개까지 살아 있을 수 있고, 더보기 → Merchant API의 권한 제한 토큰에서 만들어요. 이름을 붙이고 권한을 골라서 줘요. 하나를 폐기해도 나머지는 그대로고, 기본 토큰을 새로 발급해도 이 토큰들은 건드리지 않아요.
| 권한 | 쓸 수 있는 메서드 |
|---|---|
| (아무 유효한 토큰) | getMe, getCurrencies, getExchangeRates |
read | getBalance, getStats, getInvoices, getChecks, getTransfers, getSubscriptionPlans, getSubscriptions |
invoices | createInvoice, deleteInvoice |
refunds | refundInvoice |
payouts | transfer, transferBatch |
checks | createCheck, deleteCheck |
subscriptions | createSubscriptionPlan, archiveSubscriptionPlan, cancelSubscription |
권한은 서로 더해질 뿐 서로를 품지 않아요. invoices가 있다고 read가 되지는
않으니까, 청구서만 만드는 서버에는 아무것도 읽지 못하는 토큰을 줄 수 있어요.
토큰에 없는 권한의 메서드를 부르면 403 scope_required가 돌아와요. getMe는
지금 쓰는 토큰의 scopes(기본 토큰이면 null)와 token_name을 알려 주니까,
내가 뭘 쥐고 있는지 언제든 확인할 수 있어요.
요청과 응답
- **읽기 메서드는
GET**이고 파라미터는 쿼리 문자열로 보내요. 돈이 움직이는 메서드는POST만 받아요. 파라미터는 JSON 본문, form-urlencoded, 쿼리 파라미터로 보낼 수 있고(겹치면 본문이 이겨요),multipart/form-data는 받지 않아요. - 응답은 모두 같은 형식의 JSON이에요. 성공은
{"ok": true, "result": …}, 오류는{"ok": false, "error": {"code": <HTTP status>, "name": "<error_name>"}}. 분기는error.name으로 하세요. 기계가 읽으라고 고정해 둔 문자열이에요. - 예외가 하나 있어요. GET 메서드의 쿼리 값이 타입부터 잘못되면(예:
offset=abc) 이 형식을 벗어난{"detail": …}본문과 함께 HTTP 422가 돌아와요. 쿼리 값은 타입에 맞게 보내 주세요.
금액
- 코인 금액은 코인 단위의 소수점 문자열(
"10.5")이에요. JSON 숫자로는 절대 오지 않아요. 응답에는amount_minor(확장 기능)도 같이 오는데, 최소 단위 정수를 문자열로 담은 값이에요. wei 단위 정수는 JavaScriptNumber범위를 넘어가니까요. - 자산별
decimals는getCurrencies에서 가져와요. 금액 계산은 코드에 박지 말고 여기에 맞춰 주세요. - 법정화폐 금액은 소수점 2자리까지예요.
- 시세는 고정소수점 문자열이고, 숫자가 아니에요.
페이지 나누기
목록 메서드(getInvoices, getChecks, getTransfers,
getSubscriptions)는 offset(기본값 0)과 count(기본값 100, 최대 1000.
getSubscriptions는 최대 500)를 받고 {"items": […]}를 최신순으로 돌려줘요.
ID 필터(invoice_ids, check_ids, transfer_ids)는 쉼표로 이은 정수
목록이에요. 시각은 어디서나 ISO 8601 문자열이에요.
멱등키: spend_id
돈이 움직이는 메서드는 호출하는 쪽이 만든 spend_id(1~64자)를 받아요.
transfer와 transferBatch의 항목마다 꼭 있어야 하고, createCheck와
refundInvoice에서는 선택이에요(확장 기능이지만 넣는 게 좋아요). 같은 키에
같은 파라미터로 다시 보내면 돈이 두 번 나가는 대신 원래 결과가 그대로
돌아와요. 그래서 응답이 늦은 요청은 언제든 다시 보내도 안전해요. 같은 키에
다른 파라미터를 보내면 409 idempotency_conflict가, 원래 요청이 아직 도는
중에 다시 보내면 409 idempotency_in_progress가 돌아와요.
호출 한도
앱 단위로 걸리고, 그 앱의 모든 토큰이 함께 써요. 넘으면
429 rate_limited예요.
| 메서드 | 한도 |
|---|---|
createInvoice, createCheck | 분당 60회 |
refundInvoice, transfer | 분당 30회 |
transferBatch | 분당 10회 |
읽기 메서드에는 한도가 없어요. 플랫폼 점검 중에는 쓰기 메서드가
503 maintenance를 돌려주고, 읽기는 그대로 돌아가요.
조회와 계정 메서드
getMe
GET /pay/api/getMe — 파라미터 없음. 앱 정보를 돌려줘요. app_id,
name, payment_processing_bot_username, webhook_url, webhook_events(앱이
켜 둔 확장 webhook 종류), 그리고 위에서 설명한 토큰 확인용 필드 scopes /
token_name이에요.
getBalance
GET /pay/api/getBalance — 파라미터 없음. 지원하는 자산마다 한 줄씩, 잔액이 없어도
빠짐없이 돌려줘요. currency_code, available(쓸 수 있는 잔액),
onhold(아직 받아 가지 않은 송금 링크에 잠긴 자산), amount_minor예요.
getCurrencies
GET /pay/api/getCurrencies — 파라미터 없음. API가 무엇을 지원하는지 알려
주는 기준 목록이에요. 코인 행(is_blockchain: true)과 청구서 가격을 매길 수
있는 법정화폐 행(is_fiat: true)이 있어요. 각 행에는 code, name,
decimals, 그리고 is_stablecoin 표시가 들어 있어요.
getExchangeRates
GET /pay/api/getExchangeRates — 파라미터 없음. 코인을 법정화폐로 환산한
시세예요. source, target, rate(고정소수점 문자열), 그리고 is_valid가
있어요. is_valid가 false면 표 전체가 오래된 캐시에서 나온 거라, 참고용으로만
보세요.
getStats
GET /pay/api/getStats — start_at / end_at은 선택이에요(ISO 8601. 기본
구간은 최근 24시간). volume(그 구간에 결제된 청구서의 미국 달러 환산액),
conversion(결제/생성 비율, 퍼센트), unique_users_count,
created_invoice_count, paid_invoice_count, 그리고 실제로 쓰인 구간의 시작과
끝을 돌려줘요. 날짜를 읽지 못하면 400 invalid_date가 돌아와요.
어떤 메서드에서나 나올 수 있는 오류
| HTTP | error.name | 언제 |
|---|---|---|
| 401 | unauthorized | 토큰이 없거나 잘못됐거나 폐기됨 |
| 403 | scope_required | 토큰에 그 메서드의 권한이 없음 |
| 400 | invalid_request | 파라미터를 읽지 못하거나 값이 잘못됨(POST) |
| 429 | rate_limited | 호출 한도를 넘음 |
| 503 | maintenance | 플랫폼 점검 중(쓰기 메서드) |
| 500 | internal_error | 예상 못 한 서버 오류 |
메서드마다 따로 나오는 오류는 각 메서드 문서에 적혀 있어요.
이 문서가 도움이 됐나요?
의견 고마워요.