Skip to main content
Sentra가 통합 코드를 대신 작성하도록 하세요.
VS Code, Cursor 또는 Windsurf에서 AI assistant를 사용하면 SDK/API 코드, webhook handler, 크레딧 지급 등을 원하는 내용을 설명하는 것만으로 생성할 수 있습니다.
Sentra 사용해 보기: AI 기반 통합 →
이 튜토리얼에서는 NeuralAPI를 구축합니다. 각 구독 플랜에 월별 토큰 크레딧이 포함되고, 크레딧이 부족해지면 고객이 충전 팩을 구매할 수 있으며, 백엔드가 OpenAI에서 요청을 처리할 때 크레딧을 자동으로 차감하는 계층형 AI 플랫폼입니다.
이 튜토리얼에서는 Node.js/Express와 OpenAI SDK를 사용합니다. Dodo Payments 개념(크레딧, meter, webhook)은 모든 framework 또는 AI provider에 적용할 수 있으므로 자유롭게 맞춰 사용하세요.
이 튜토리얼을 완료하면 다음 방법을 알게 됩니다:
  • 사용자 지정 크레딧 entitlement(토큰)과 이를 자동으로 차감하는 meter 생성
  • 구독 플랜(초과 사용 허용 및 비허용)과 일회성 충전 제품에 크레딧 연결
  • 실제 OpenAI completion endpoint를 연결하고 Dodo Payments을 통해 토큰 결제
  • SDK를 통해 고객의 실시간 크레딧 잔액 조회
  • webhook signature를 검증하고 Dodo Payments 크레딧 이벤트 라우팅

구축할 내용

NeuralAPI의 가격 모델은 다음과 같습니다:
시작하기 전에 다음을 준비하세요:
  • Dodo Payments 계정(test mode도 가능)
  • OpenAI API key
  • Node.js 18+
  • TypeScript/Node.js 기본 지식

1단계: 토큰 크레딧 Entitlement 생성

먼저 두 구독 플랜과 충전 팩이 공유할 크레딧 entitlement를 생성합니다. 이를 플랫폼에서 사용하는 “토큰” 단위를 정의하는 과정이라고 생각하면 됩니다.
생성된 크레딧 entitlement가 표시된 크레딧 목록 페이지

The Credits tab under Products shows all your credit entitlements.

1

Navigate to Credits

  1. Dodo Payments dashboard에 로그인합니다.
  2. 왼쪽 sidebar에서 Products를 클릭합니다.
  3. Credits 탭을 선택합니다.
  4. Create Credit을 클릭합니다.
2

Configure the credit unit

토큰 크레딧의 기본 정보를 입력합니다:Credit Name: API TokensCredit Type: Custom Unit 선택Unit Name: tokenPrecision: 0 (토큰은 항상 정수입니다)Credit Expiry: 30 days (각 billing cycle마다 크레딧이 초기화됩니다)
크레딧을 생성한 후에는 Precision을 변경할 수 없습니다. 토큰 수에는 0(정수)가 거의 항상 올바른 설정입니다.
3

Skip overage at the credit level

여기서는 초과 사용을 비활성화 상태로 두세요. 크레딧을 제품에 연결할 때 플랜별로 설정합니다. 그러면 Starter 플랜은 잔액이 0이 되면 사용을 차단하고 Pro 플랜은 초과 사용을 허용할 수 있습니다.
여기서 설정한 초과 사용 설정은 기본값입니다. 각 제품 연결에서 이를 재정의할 수 있으며, 3단계에서 바로 그렇게 합니다.
4

Save and copy the credit ID

Create Credit을 클릭합니다. 저장한 후 크레딧을 열고 ID를 복사합니다. ID는 cent_xxxxxxxxxxxx와 같은 형식입니다.
API Tokens 크레딧 entitlement가 준비되었습니다. 이제 사용량 이벤트가 자동으로 차감을 수행할 수 있도록 meter를 생성합니다.

2단계: 토큰 사용량용 Meter 생성

meter는 들어오는 사용량 이벤트를 집계하고 이를 크레딧 차감으로 변환합니다. 3단계에서 제품을 생성할 때 meter를 연결하므로, 플랜 제품을 만들기 전에 생성해야 합니다.
1

Open the Meters section

  1. dashboard sidebar에서 ProductsMeters로 이동합니다.
  2. Create Meter를 클릭합니다.
2

Configure the meter

다음과 같이 입력합니다:Meter Name: Token Usage MeterEvent Name: api.tokens_used (앱이 전송하는 값과 정확히 일치해야 합니다)Aggregation Type: Sum — 각 이벤트의 토큰 수를 합산합니다.Over Property: tokens — 각 이벤트에서 합산할 값이 있는 metadata key입니다.Measurement Unit: tokens
이벤트 이름은 대소문자를 구분합니다. api.tokens_usedApi.Tokens.Used이므로 하나를 선택해 일관되게 사용하세요.
meter를 저장하고 ID를 복사합니다. 제품에 연결할 때 참조하게 됩니다.
Meter가 생성되었습니다. 이제 제품을 설정할 때 이를 크레딧에 연결할 수 있습니다.

3단계: 플랜 제품 생성

두 플랜 모두 일반 Subscription이 아닌 Usage Based Billing 제품이어야 합니다. meter는 UBB 제품에만 연결할 수 있으며 고객이 API를 호출할 때 크레딧을 자동 차감하려면 meter가 필요합니다. UBB 제품은 반복되는 기본 요금( $29 / $99)도 지원합니다. 이 기본 요금에 더해 발생한 사용량은 크레딧으로 결제됩니다.
Usage Based Billing 가격 설정

Usage Based Billing pricing type with meter configuration.

Starter Plan ($29/월 — 10M 토큰, 초과 사용 없음)

1

Create the Starter UBB product

  1. Products → Create Product로 이동합니다.
  2. 가격 유형으로 Usage Based Billing을 선택합니다.
  3. 다음을 입력합니다:
Product Name: NeuralAPI StarterDescription: 10 million API tokens per month. Perfect for individual developers and small projects.Fixed Price: 29.00 (반복되는 기본 요금으로, 사용량이 없어도 매월 청구됩니다)Billing Cycle: MonthlyCurrency: USD
2

Attach the meter

Select meter 섹션에서 **+**를 클릭하고 Token Usage Meter를 추가합니다. 그런 다음 meter에서 다음을 설정합니다:
  1. Bill usage in Credits를 켭니다.
  2. Credit Entitlement: API Tokens를 선택합니다.
  3. Meter units per credit: 1 — 이벤트의 각 토큰이 차감되는 크레딧 1개에 매핑됩니다.
  4. Free Threshold: 0 — 크레딧 할당 자체가 고객의 “free tier”이므로 추가 무료 구간은 필요하지 않습니다.
Bill usage in Credits가 활성화되고 API Tokens가 선택된 meter

Toggle 'Bill usage in Credits' on the meter and pick the credit entitlement.

이 설정이 들어오는 api.tokens_used 이벤트를 고객 잔액에서 실제로 차감하도록 연결합니다.
3

Configure credit issuance for Starter

제품 화면에서 credit-billed meter를 연결하면 표시되는 크레딧 설정 섹션으로 스크롤합니다:Credits issued per billing cycle: 10000000Allow Overage: Disabled — Starter 고객은 토큰이 소진되면 차단됩니다.Import Default Credit Settings: Enabled — 크레딧 entitlement의 30일 만료를 사용합니다.
주기별 금액과 초과 사용 설정이 있는 크레딧 설정 양식

Configure credit issuance per cycle on the UBB product.

Save를 클릭하고 제품 ID를 복사합니다.
Starter Plan: 월 기본 요금 $29, 주기당 10M 토큰, 잔액 0에서 차단, meter를 통한 자동 차감.

Pro Plan ($99/월 — 40M 토큰, 초과 사용 허용)

1

Create the Pro UBB product

Starter와 같은 흐름으로 진행하되 수치만 더 크게 설정합니다:Product Name: NeuralAPI ProDescription: 40 million API tokens per month with overage. Built for production applications.Fixed Price: 99.00Billing Cycle: MonthlyCurrency: USD
2

Attach the meter

Starter와 동일하게 Token Usage Meter를 추가하고, Bill usage in Credits를 켜고, API Tokens를 선택한 다음 Meter units per credit1, Free Threshold0로 설정합니다.
3

Configure credit issuance with overage

이번에는 초과 사용을 활성화하여 크레딧 발급을 설정합니다:Credits issued per billing cycle: 40000000Import Default Credit Settings: Disable — 제품별로 초과 사용 설정을 사용자 지정해야 합니다.Allow Overage: EnabledPrice Per Unit: 0.000005 USD/토큰 (즉, 1K 토큰당 0.005또는1M토큰당0.005 또는 1M 토큰당 5이며, 초과 사용을 억제하기 위해 플랜의 유효 토큰당 요금보다 높게 설정합니다)Overage Behavior: Bill overage at billing — 초과 사용 요금은 다음 invoice에 청구된 후 잔액이 초기화됩니다.제품을 저장하고 제품 ID를 복사합니다.
Pro Plan: 월 기본 요금 99,주기당40M토큰,1K토큰당99, 주기당 40M 토큰, 1K 토큰당 0.005의 초과 사용, meter를 통한 자동 차감.

4단계: 토큰 충전 팩 생성

충전 팩은 기존 고객의 잔액에 5,000,000 토큰을 추가하는 일회성 구매 제품입니다.
Single Payment가 선택된 제품 가격 섹션

Single Payment pricing selected for a one-time credit product.

1

Create a one-time product

  1. Products → Create Product로 이동합니다.
  2. 가격 유형으로 Single Payment를 선택합니다.
  3. 다음을 입력합니다:
Product Name: Token Top-Up PackDescription: Instantly add 5 million tokens to your NeuralAPI balance.Price: 19.00Currency: USD
2

Attach the token credit

  1. Entitlements 섹션에서 Credits 옆의 Attach를 클릭합니다.
  2. API Tokens를 선택합니다.
  3. Credits issued5000000로 설정합니다.
  4. Import Default Credit SettingsDisable합니다. 기본 30일 만료를 재정의하려는 목적입니다.
  5. Credit Expiry365 days로 설정합니다.
  6. 제품을 저장합니다.
제품 ID를 복사합니다.
충전 팩의 만료 기간을 더 길게 설정하는 이유는 무엇일까요? 구독 크레딧은 주기가 30일이므로 30일마다 초기화됩니다. 충전 팩은 선불 구매이므로 고객은 $19를 미리 지불하고 해당 토큰이 한 달 이상 유지되기를 기대합니다. 365일은 OpenAI, AWS, Anthropic에서 실제 선불 크레딧이 작동하는 방식과 일치하면서도 고객이 무기한으로 크레딧을 축적하지 못하도록 책임을 제한합니다.
충전 팩이 설정되었습니다. 구매하면 365일 동안 유효한 5,000,000 토큰이 지급됩니다.

5단계: 백엔드 구축

이제 구독 checkout, 충전 checkout, 토큰 결제가 적용된 실제 OpenAI completion, 잔액 조회 및 크레딧 webhook 이벤트를 처리하는 Express server를 구축합니다.
1

Set up your project

tsconfig.json을 생성합니다:
tsconfig.json
package.json scripts를 업데이트합니다:
package.json
2

Set up environment variables

이전 단계의 자격 증명과 ID를 사용해 .env를 생성합니다:
.env
.env를 version control에 절대 commit하지 마세요. 즉시 .gitignore에 추가합니다.
webhook endpoint를 등록한 후 7단계에서 DODO_PAYMENTS_WEBHOOK_KEY를 입력합니다.
3

Implement the server

src/server.ts를 생성합니다:
백엔드가 완성되었습니다. 구독 checkout, 충전 checkout, meter가 적용된 OpenAI completion, 잔액 조회 및 검증된 webhook handler가 포함됩니다.
@dodopayments/ingestion-blueprintsusageEvents.ingest 호출을 자동화하는 즉시 사용 가능한 tracker를 제공합니다. LLM Blueprint, API gateway, object storage, streams, time-range 사용량이 포함됩니다.
4

A note on how deductions actually happen

명시적인 “N개 크레딧 차감” 호출이 없다는 것을 알아차렸을 수 있습니다. 이는 의도된 설계입니다:
  1. handler가 OpenAI를 호출하고 usage.total_tokens(예: 1532)를 반환받습니다.
  2. 단일 사용량 이벤트를 수집합니다: event_name: api.tokens_used, metadata: { tokens: 1532 }.
  3. Token Usage Meter가 고객별로 이벤트를 집계합니다.
  4. meter가 Bill usage in Credits를 사용해 API Tokens 크레딧에 연결되어 있으므로, Dodo Payments가 고객의 만료되지 않은 가장 오래된 지급분에서 1532 크레딧을 차감합니다(FIFO).
  5. 초과 사용이 활성화되어 고객 잔액이 0 미만이 되면 부족분이 추적되고 다음 invoice에 청구됩니다.
이 모든 작업을 meter가 처리합니다. 코드에서는 이벤트만 수집하면 됩니다.

6단계: Demo Frontend 추가

브라우저에서 모든 흐름을 테스트할 수 있도록 public/index.html를 생성합니다. 고객 ID를 localStorage에 저장하므로 subscribe → generate → top-up이 동일한 identity를 공유하며 로그인된 앱을 재현합니다:

7단계: Webhook 연결

Webhook을 사용하면 server가 잔액 변경에 반응할 수 있습니다. 고객의 잔액이 0이 되기 전에 “잔액 부족” 이메일을 보내는 데 사용합니다.
1

Expose your local server

Webhook에는 public URL이 필요합니다. local development에서는 ngrok 또는 다른 tunnel을 사용하세요:
https://...ngrok-free.app URL을 복사합니다.
2

Register the webhook in Dodo Payments

  1. dashboard에서 Developers → Webhooks → Add Endpoint로 이동합니다.
  2. URL: https://your-tunnel.ngrok-free.app/webhooks/dodo
  3. 최소한 다음 이벤트를 subscribe합니다:
    • credit.added
    • credit.deducted
    • credit.overage_charged
  4. 저장하고 Signing Secret을 복사합니다.
  5. 이를 .envDODO_PAYMENTS_WEBHOOK_KEY로 붙여넣은 다음 npm run dev를 다시 시작합니다.
SDK의 dodo.webhooks.unwrap()가 signing secret을 사용해 webhook-id, webhook-timestampwebhook-signature header를 검증합니다. HMAC verification을 직접 구현할 필요가 없습니다. 구현해서도 안 됩니다. Dodo Payments는 Standard Webhooks를 사용하며 body만이 아니라 id.timestamp.body에 signature를 적용하기 때문입니다.

8단계: 전체 흐름 테스트

1

Subscribe a test customer

  1. npm run dev를 실행합니다.
  2. http://localhost:3000를 엽니다.
  3. Pro Plan을 선택하고 테스트 email과 name을 입력한 후 Get Checkout Link를 클릭합니다. test card details로 checkout을 완료합니다.
  4. dashboard에서 Customers → most recent로 이동하고 cus_... ID를 복사합니다.
  5. 이를 demo의 “Logged-in customer ID” 필드에 붙여넣고 Save를 클릭합니다.
고객에게 40,000,000 토큰이 있어야 합니다. Refresh Balance를 클릭해 확인합니다.
2

Generate a real AI response

prompt를 입력하고 Generate를 클릭합니다. server가 OpenAI를 호출하고 실제 total_tokens를 반환받은 뒤 사용량 이벤트를 수집하고 응답을 반환합니다.
사용량 이벤트는 약 1분마다 background worker가 처리합니다. 잔액은 즉시 줄어들지 않습니다. 30~90초 기다린 뒤 다시 Refresh Balance를 클릭하세요. 첫 번째 새로 고침에서 변동이 보이지 않는다고 문제가 있다고 판단하지 마세요.
3

Test the top-up flow

Buy 5M Tokens — $19를 클릭하고 checkout을 완료합니다. 결제가 성공한 후 잔액을 새로 고치면 5,000,000 토큰이 증가해야 합니다. server log에는 credit.added 이벤트가 표시되어야 합니다.

문제 해결

가능한 원인:
  • meter의 이벤트 이름이 전송하는 event_name와 일치하지 않음(api.tokens_used는 대소문자를 구분함)
  • meter가 제품의 API Tokens 크레딧에 연결되지 않음. 제품의 meter 설정으로 이동해 Bill usage in Credits가 켜져 있는지 확인
  • metadata.tokens key가 meter의 “Over Property” 필드와 일치하지 않음
  • 고객의 grant가 만료됨(고객의 크레딧 history 확인)
확인할 항목:
  1. Products → Meters: meter를 열고 제품 연결에 연결된 크레딧 이름이 표시되는지 확인
  2. meter의 Events 탭: 차감 전에도 수집된 이벤트가 여기에 표시되어야 함
  3. Customers → [Customer] → Credits: 1~2분 이내에 ledger entry가 표시되어야 함
가능한 원인:
  • 고객이 아직 checkout을 완료하지 않음. 크레딧은 결제가 성공한 후에만 지급됨
  • 잘못된 customer_id로 조회함(dashboard의 cus_... ID를 사용하며 자체 DB ID는 사용하지 않음)
  • .envCREDIT_ENTITLEMENT_ID가 제품에 연결된 크레딧과 일치하지 않음
확인할 항목: Customers → [Customer] → Credits를 엽니다. 크레딧이 표시되지 않으면 제품 entitlement가 연결되지 않았거나 결제가 완료되지 않은 것입니다.
가능한 원인:
  • Pro product의 credit attachment에서 초과 사용이 활성화되지 않음(credit-level 설정은 기본값일 뿐임)
  • 고객이 실제로는 Pro가 아니라 Starter를 사용 중임
  • 초과 사용 limit가 0으로 설정됨
확인할 항목: Pro → Entitlements → Credits를 편집하고 Allow Overage가 켜져 있으며 Price Per Unit0.000005인지 확인합니다(= 1백만 토큰당 $5. 앞의 0을 다시 확인하세요. 이 필드는 1K당 가격이 아니라 토큰당 가격을 입력합니다).
가능한 원인:
  • Body parsing 순서: express.json()/webhooks/dodoexpress.raw()보다 먼저 적용됨. SDK에는 parsing된 JSON이 아니라 request의 raw bytes가 필요함
  • DODO_PAYMENTS_WEBHOOK_KEY의 signing secret이 잘못됨
  • Reverse proxy가 header를 재작성함
확인할 항목: app.use('/webhooks/dodo', express.raw(...)) line이 server.ts에서 app.use(express.json())보다 앞에 있는지 확인합니다.

도움이 필요하신가요?

축하합니다! NeuralAPI에 크레딧 기반 결제를 구축했습니다

이제 플랫폼에 완전한 production-ready 크레딧 결제 시스템이 갖춰졌습니다:

Token Credit Entitlement

모든 플랜과 충전 팩에서 공유하는 30일 만료의 재사용 가능한 API Tokens 크레딧

Tiered Plans, One Credit

크레딧을 중복 생성하지 않고 제품별로 설정된 Starter(10M, hard limit)와 Pro(40M + 초과 사용)

One-Time Top-Up Pack

고객이 구독을 변경하지 않고 $19에 5M 토큰을 추가

Auto-Deduction via Meter

실제 OpenAI 토큰 수를 이벤트로 수집하고, 수동 추적 없이 meter가 FIFO 방식으로 크레딧 차감

Live Balance API

SDK를 통한 실시간 잔액으로 access를 제어하고, 사용량을 표시하거나 앱에서 고객에게 경고

Verified Webhook Pipeline

SDK의 Standard Webhooks helper를 사용해 signature가 검증된 handler로 라우팅되는 크레딧 ledger 이벤트(credit.added, credit.deducted, credit.overage_charged)
production으로 전환하시나요? 다음 설정을 강화하세요:
  • /credits/:customerId/api/generate에 auth 적용 — 현재는 누구나 임의의 customer ID로 호출할 수 있습니다. 사용자를 인증하고 server-side에서 해당 사용자의 customer ID를 조회하세요.
  • 안정적인 event_ids — 예제에서는 Date.now() + random를 사용합니다. production에서는 request ID를 사용해 retry가 idempotent하도록 하세요(Dodo Payments가 event_id별로 중복 제거함).
  • customer↔user mapping 저장 — 첫 checkout 후 DB에 customer_id를 저장하여 수동으로 붙여넣는 단계를 없애세요.
  • 구독 종료 시 동작 결정 — 플랜 크레딧은 자연 만료(지급 후 30일)까지 고객 ledger에 남고 충전 크레딧은 365일 동안 유효합니다. 하지만 cookbook의 /api/generate는 구독 상태가 아니라 잔액만 확인합니다. 따라서 취소된 고객도 남은 토큰을 사용할 수 있습니다. 이는 소비자 친화적인 기본 동작입니다. 더 엄격한 access control이 필요하면 (a) subscription.cancelled webhook을 수신해 구독 상태에 따라 /api/generate를 허용하거나, (b) Dodo의 ledger API를 호출해 취소 시 사용하지 않은 플랜 크레딧을 차감하되 충전 크레딧은 유지하세요.
  • Usage Billing dashboard를 모니터링하여 metering 이상을 조기에 발견하세요.

Credit-Based Billing Reference

전체 CBB 문서: rollover, 초과 사용 mode, ledger management 및 모든 API endpoint.

Credit Webhook Events

server가 수신할 수 있는 모든 크레딧 이벤트의 payload schema.
마지막 수정일 2026년 7월 31일