tgpay cryptoAPI
crypto-payapireferencetokens

Merchant API 레퍼런스

읽는 데 4분마지막 수정 2026년 8월 22일

모든 메서드가 함께 쓰는 규칙과, 읽기 전용 조회 메서드예요. 메서드별 문서는 청구서와 환불, 송금과 송금 링크, 구독, webhook에 있어요.

이 API는 Crypto Bot과 호환돼요. 이미 Crypto Bot으로 붙여 둔 연동이라면 기본 URL과 토큰만 바꾸면 돌아가요. 그 규격을 넘어서는 것은 아래에서 확장 기능이라고 표시해 뒀어요.

메서드와 객체, 오류 이름, webhook까지 전부 담은 OpenAPI 3.1 명세도 이 문서 옆에 같이 두었어요. crypto-pay-openapi.yaml · crypto-pay-openapi.json. 코드 생성기나 API 클라이언트, AI 도구에 그대로 넣어 쓰면 돼요.

기본 URL과 인증

모든 메서드는 https://crypto.tgpaybot.com/pay/api/<methodName>에 있어요.

요청마다 TgCryptoPay-API-Token 헤더에 토큰을 담아 인증해요 (Crypto-Pay-API-Token도 호환용 별칭으로 받아 주고, 둘 다 보내면 원래 헤더가 이겨요). 토큰이 없거나 잘못됐거나 폐기됐을 때, 그리고 지운 앱의 토큰일 때는 401 unauthorized가 돌아와요.

토큰은 <app_id>:<secret> 모양이고, 만들거나 새로 발급할 때 한 번만 보여 줘요. 서버에는 해시만 남아요. 개발자로 시작하기를 보세요.

토큰과 권한

인증하는 방식이 똑같은 두 가지 열쇠가 있어요.

  • 기본 토큰 — 모든 메서드를 쓸 수 있고, webhook에 서명하는 유일한 열쇠예요.
  • 권한 제한 토큰(확장 기능) — 앱마다 최대 10개까지 살아 있을 수 있고, 더보기 → Merchant API권한 제한 토큰에서 만들어요. 이름을 붙이고 권한을 골라서 줘요. 하나를 폐기해도 나머지는 그대로고, 기본 토큰을 새로 발급해도 이 토큰들은 건드리지 않아요.
권한쓸 수 있는 메서드
(아무 유효한 토큰)getMe, getCurrencies, getExchangeRates
readgetBalance, getStats, getInvoices, getChecks, getTransfers, getSubscriptionPlans, getSubscriptions
invoicescreateInvoice, deleteInvoice
refundsrefundInvoice
payoutstransfer, transferBatch
checkscreateCheck, deleteCheck
subscriptionscreateSubscriptionPlan, 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 단위 정수는 JavaScript Number 범위를 넘어가니까요.
  • 자산별 decimalsgetCurrencies에서 가져와요. 금액 계산은 코드에 박지 말고 여기에 맞춰 주세요.
  • 법정화폐 금액은 소수점 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자)를 받아요. transfertransferBatch의 항목마다 꼭 있어야 하고, createCheckrefundInvoice에서는 선택이에요(확장 기능이지만 넣는 게 좋아요). 같은 키에 같은 파라미터로 다시 보내면 돈이 두 번 나가는 대신 원래 결과가 그대로 돌아와요. 그래서 응답이 늦은 요청은 언제든 다시 보내도 안전해요. 같은 키에 다른 파라미터를 보내면 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_validfalse면 표 전체가 오래된 캐시에서 나온 거라, 참고용으로만 보세요.

getStats

GET /pay/api/getStatsstart_at / end_at은 선택이에요(ISO 8601. 기본 구간은 최근 24시간). volume(그 구간에 결제된 청구서의 미국 달러 환산액), conversion(결제/생성 비율, 퍼센트), unique_users_count, created_invoice_count, paid_invoice_count, 그리고 실제로 쓰인 구간의 시작과 끝을 돌려줘요. 날짜를 읽지 못하면 400 invalid_date가 돌아와요.

어떤 메서드에서나 나올 수 있는 오류

HTTPerror.name언제
401unauthorized토큰이 없거나 잘못됐거나 폐기됨
403scope_required토큰에 그 메서드의 권한이 없음
400invalid_request파라미터를 읽지 못하거나 값이 잘못됨(POST)
429rate_limited호출 한도를 넘음
503maintenance플랫폼 점검 중(쓰기 메서드)
500internal_error예상 못 한 서버 오류

메서드마다 따로 나오는 오류는 각 메서드 문서에 적혀 있어요.