SDK 레퍼런스
@modfolio/pay-sdk는 Modfolio Pay API를 위한 공식 TypeScript SDK입니다. 완전한 타입 안전성과 자동완성을 제공합니다.
설치
bun add @modfolio/pay-sdkSDK는 TypeScript 타입 정의를 내장하고 있어 별도의 @types 패키지가 필요 없습니다.
클라이언트 생성
createPayClient() 팩토리 함수로 클라이언트를 생성합니다. 인증 방식에 따라 세 가지 설정이 가능합니다.
Bearer JWT
import { createPayClient } from "@modfolio/pay-sdk";
const pay = createPayClient({
baseUrl: "https://my.modfolio.io",
auth: {
type: "bearer",
token: session.accessToken,
},
});API Key
const pay = createPayClient({
baseUrl: "https://my.modfolio.io",
auth: {
type: "api-key",
key: process.env.MODFOLIO_PAY_KEY,
sourceApp: "gistcore",
userId: "user_abc123",
},
});Agent Key
const pay = createPayClient({
baseUrl: "https://my.modfolio.io",
auth: {
type: "agent-key",
key: process.env.MODFOLIO_AGENT_KEY,
sourceApp: "gistcore",
},
});리소스 그룹
SDK는 API 리소스를 그룹별로 구성합니다. 각 그룹은 pay.<group>.<method>() 형태로 접근합니다.
pay.orders
주문 생성, 조회, 취소
create()list()get(id)cancel(id)pay.subscriptions
구독·1개월 이용권 조회 · 해지 (M2M). 정기결제 생성(create)은 현재 제공하지 않음 — 400 recurring_disabled
create()list()cancel(id)pay.wallets
월렛 잔액·거래 내역 조회. 충전(topUp)·차감(charge · chargeAction)은 현재 제공하지 않음 — 403 credits_disabled
get()topUp()charge()chargeAction()transactions()pay.creditRates
크레딧 레이트 관리 — 크레딧 차감을 제공하지 않아 현재 과금에 쓰이지 않음
create()list()get(id)update(id)delete(id)pay.paymentIntents
에이전틱 결제 승인 흐름 (생성 → 승인/거절 → 실행)
create()get(id)approve(id)reject(id)execute(id)cancel(id)pay.approvalRules
지출 승인 규칙
create()list()deactivate(id)pay.budgetAlerts
예산 임계 알림
create()list()deactivate(id)pay.webhooks
웹훅 엔드포인트 관리
create()list()get(id)update(id)delete(id)에러 처리
API 요청이 실패하면 PayApiError가 throw됩니다. HTTP 상태 코드(status), 응답에 코드가 있으면 안정된 에러 코드(code · 0.1.1+), 메시지를 포함합니다.
import { PayApiError } from "@modfolio/pay-sdk";
try {
await pay.wallets.chargeAction({
sourceApp: "gistcore",
actionCode: "ai_generation",
idempotencyKey: "req_001",
});
} catch (error) {
if (error instanceof PayApiError) {
switch (error.code) {
case "credits_disabled":
// 크레딧 미제공 — 1개월 이용권 구매로 안내
break;
case "QUOTA_EXCEEDED":
// 할당량 소진 — 상위 이용권 안내
break;
case "RATE_NOT_FOUND":
// 알 수 없는 actionCode
break;
default:
// 코드가 없는 거부(사용 한도 초과 403 · 429 등)는 error.status 로 분기
break;
}
console.error(error.status, error.code, error.message);
}
}에러 코드
구조화된 오류는 error.code 로 분기합니다. 전체 목록과 각 코드의 재시도 가능 여부 · 권장 조치는 GET /api/v1/catalog/errors 가런타임에 돌려줍니다 — 아래 표는 그 일부입니다.
| HTTP | 코드 | 설명 |
|---|---|---|
| 402 | INSUFFICIENT_CREDITS | 월렛 잔액이 요청 금액보다 적음 |
| 403 | QUOTA_EXCEEDED | 이 액션의 월 할당량 소진 (초과 사용 불가) |
| 403 | credits_disabled | 크레딧 충전·차감이 현재 제공되지 않음 |
| 400 | recurring_disabled | 정기결제(구독) 생성이 현재 제공되지 않음 — 1개월 이용권으로 판매 |
| 400 | pass_not_modifiable | 1개월 이용권은 일시정지·플랜 변경 불가 — 다른 플랜은 새로 구매 |
| 404 | RATE_NOT_FOUND | 해당 sourceApp · actionCode 의 크레딧 레이트 미설정 |
| 404 | INTENT_NOT_FOUND | 결제 인텐트를 찾을 수 없음 |
| 409 | INTENT_ALREADY_EXECUTED | 이미 실행된 인텐트 |
| 409 | INTENT_NOT_APPROVED | 승인 전에는 실행할 수 없음 (승인 후 재시도) |
| 409 | INTENT_CANCELLED | 취소된 인텐트 |
| 410 | INTENT_EXPIRED | 인텐트 만료 — 새로 생성 후 재시도 |
대소문자 규약 — 에이전트 결제·크레딧 경로는SCREAMING_CASE(레지스트리 AGENT_ERROR_CODES), 일반 라우트 수준 거부는 snake_case(credits_disabled · consent_required)입니다. 둘 다 error.code 에 그대로 실립니다.
TypeScript 지원
SDK는 모든 요청/응답에 대해 완전한 타입 정의를 제공합니다. 에디터에서 자동완성과 타입 검증을 활용하세요.
// 모든 응답 타입이 자동 추론됩니다
const wallet = await pay.wallets.get();
// ^? { balance: number; currency: string; ... }
// 요청 파라미터도 타입 검증됩니다
await pay.subscriptions.create({
priceId: "price_abc",
// ^? string (자동완성 지원)
});