Skip to main content
To have your coding agent write the integration, install the Dodo Agent Plugin. It adds the Dodo Payments skills and MCP servers to Claude Code, Codex CLI, Cursor, VS Code / GitHub Copilot, Kiro, and OpenCode.
You’ll build NeuralAPI, a tiered AI API where each subscription plan includes a monthly allowance of token credits. Customers who run low buy a top-up pack, and your backend reports the tokens each OpenAI request uses so Dodo Payments deducts them from the customer’s balance.
This tutorial uses Node.js, Express, and the OpenAI SDK. The Dodo Payments concepts (credits, meters, and webhooks) work the same with any framework or AI provider.
When you finish, you’ll know how to:
  • Create a custom credit entitlement for tokens, and a meter that deducts from it.
  • Attach credits to subscription plans, with and without overage, and to a one-time top-up product.
  • Call OpenAI from an endpoint that bills tokens through Dodo Payments.
  • Read a customer’s live credit balance with the SDK.
  • Verify webhook signatures and route Dodo Payments credit events.

What We’re Building

NeuralAPI sells three products: Before you start, you need:
  • A Dodo Payments account. Build everything in test mode.
  • An OpenAI API key.
  • Node.js 22 or later, and working knowledge of TypeScript and Node.js.

Step 1: Create Your Token Credit Entitlement

Create the credit entitlement that both plans and the top-up pack share. It defines the token unit NeuralAPI sells.
Credits listing page showing created credit entitlements

The Credits tab under Products shows all your credit entitlements.

1

Navigate to Credits

  1. Log in to the Dodo Payments dashboard.
  2. Click Products in the sidebar.
  3. Select the Credits tab.
  4. Click Create Credit.
2

Configure the Credit Unit

Enter these values:Credit Name: API TokensCredit Type: Custom UnitUnit Name: tokenDefine Precision: 0. Token counts are whole numbers.Credit Expiry: 30 days. Credits expire 30 days after they’re issued, which matches the monthly billing cycle.
Precision can’t be changed after you create the credit. For token counts, use 0.
3

Skip Overage at the Credit Level

Leave overage disabled on the credit. You configure it per plan when you attach the credit to each product, so the Starter plan can block usage at zero while the Pro plan allows overage.
Overage settings on the credit are defaults. Each product attachment can override them, which Step 3 does for the Pro plan.
4

Save and Copy the Credit ID

Click Create Credit. Open the saved credit and copy its ID, which starts with cde_.
The API Tokens credit entitlement is ready. Next, create a meter so that usage events deduct credits.

Step 2: Create a Meter for Token Usage

A meter aggregates incoming usage events. When you link it to a credit, the aggregated usage is deducted from the customer’s credit balance. Create the meter before the plan products, because you attach it while you create them in Step 3.
1

Open the Meters Section

  1. In the dashboard sidebar, go to Products → Meters.
  2. Click Create Meter.
2

Configure the Meter

Enter these values:Meter Name: Token Usage MeterEvent Name: api.tokens_used. This must match the event_name your app sends.Aggregation Type: Sum, to add up the token count from each event.Over Property: tokens, the metadata key whose value is summed.Measurement Unit: tokens
Event names are case-sensitive: api.tokens_used and Api.Tokens.Used are different events. You can’t edit a meter after you create it, so check every value before you confirm.
Create the meter. You select it by name when you attach it to products.
The meter is created. Next, link it to the credit on each plan product.

Step 3: Create the Plan Products

Create both plans with the Usage Based Billing pricing type, not plain Subscription. Meters attach to Usage Based Billing products, and the meter is what deducts credits as customers call your API. A Usage Based Billing product still charges a recurring base fee ($29 or $99), and usage on top of it is billed in credits.
Usage Based Billing pricing configuration

Usage Based Billing pricing type with meter configuration.

Starter Plan ($29/month — 10M Tokens, No Overage)

1

Create the Starter Product

  1. Go to Products and click Add Product.
  2. Under Pricing Type, select Usage Based Billing.
  3. Enter these values:
Product Name: NeuralAPI StarterDescription: 10 million API tokens per month. Perfect for individual developers and small projects.Price: 29.00. This is the recurring base fee, charged every month even before any usage.Repeat payment every: 1 monthCurrency: USD
2

Attach the Meter

In the Select meter section, click + and add Token Usage Meter. Then configure the meter:
  1. Turn on Bill usage in credits.
  2. Select credit: API Tokens
  3. Meter units per credit: 1. Each token in an event deducts one credit.
  4. Free Threshold: 0. The free threshold applies only when a meter bills in money. When it bills in credits, every unit is deducted from the balance.
Meter with Bill usage in Credits enabled and API Tokens selected

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

This link is what makes incoming api.tokens_used events deduct from the customer’s balance.
3

Configure Credit Issuance for Starter

After you attach a credit-billed meter, the product shows a credit configuration section. Enter:Credits issued per billing cycle: 10000000Import Default Credit Settings: on, so the product uses the 30-day expiry from the credit entitlement.Allow Overage: off. The default from Step 1 keeps overage disabled, so Starter customers stop at zero.
Credit configuration form with per-cycle amount and overage settings

Configure credit issuance per cycle on the UBB product.

Save the product and copy its ID, which starts with pdt_.
Starter Plan: $29/month base fee, 10M tokens per cycle, blocked at zero, and deducted through the meter.

Pro Plan ($99/month — 40M Tokens, Overage Enabled)

1

Create the Pro Product

Follow the Starter flow with these values:Product Name: NeuralAPI ProDescription: 40 million API tokens per month with overage. Built for production applications.Price: 99.00Repeat payment every: 1 monthCurrency: USD
2

Attach the Meter

Configure the meter as you did for Starter: add Token Usage Meter, turn on Bill usage in credits, select API Tokens, and set Meter units per credit to 1 and Free Threshold to 0.
3

Configure Credit Issuance with Overage

Configure credit issuance, this time with overage enabled:Credits issued per billing cycle: 40000000Import Default Credit Settings: off, so you can set overage for this product.Allow Overage: onPrice Per Unit: 0.000005 USD per token. That is $0.005 per 1K tokens, or $5 per 1M tokens, which is above the plan’s effective per-token rate and discourages overage.Overage Behavior: Bill overage at billing. Overage is charged on the next invoice, and then the balance resets.Save the product and copy its ID.
Pro Plan: $99/month base fee, 40M tokens per cycle, overage at $0.005 per 1K tokens, and deducted through the meter.

Step 4: Create the Token Top-Up Pack

The top-up pack is a one-time purchase that adds 5,000,000 tokens to an existing customer’s balance.
Product pricing section with Single Payment selected

One-time pricing selected for a credit product.

1

Create a One-Time Product

  1. Go to Products and click Add Product.
  2. Under Pricing Type, select One Time.
  3. Enter these values:
Product Name: Token Top-Up PackDescription: Add 5 million tokens to your NeuralAPI balance.Price: 19.00Currency: USD
2

Attach the Token Credit

  1. In the Entitlements section, click Attach next to Credits.
  2. Select API Tokens.
  3. Set No of credits issued to 5000000.
  4. Turn off Import Default Credit Settings to override the default 30-day expiry.
  5. Set Credit Expiry to Custom and enter 365 days.
  6. Save the product.
Copy the product ID.
Why a longer expiry on top-ups? Subscription credits expire after 30 days because that’s the billing cycle. A top-up is a prepaid purchase: the customer paid $19 upfront and expects the tokens to last longer than a month. A 365-day expiry matches how prepaid API credits work at OpenAI and Anthropic, where purchased credits expire one year after purchase, and still caps your liability so customers can’t stockpile credits indefinitely.
The Top-Up Pack is configured. Buying it grants 5,000,000 tokens that stay valid for 365 days.

Step 5: Build the Backend

Build the Express server. It creates subscription and top-up checkouts, calls OpenAI and bills the tokens, reads balances, and receives credit webhook events.
1

Set Up Your Project

Create a tsconfig.json:
tsconfig.json
Update package.json scripts:
package.json
2

Set Up Environment Variables

Create .env with a test mode API key from Developer → API Keys and the IDs from the previous steps:
.env
Never commit .env to version control. Add it to .gitignore before your first commit.
You fill in DODO_PAYMENTS_WEBHOOK_KEY in Step 7, after you register the webhook endpoint.
3

Implement the Server

Create src/server.ts. The completion endpoint calls OpenAI’s gpt-6-luna model, which suits high-volume requests. The package.json tab shows the full dependency list:
The backend is done: subscription checkout, top-up checkout, an OpenAI completion with metered token billing, a balance read, and a verified webhook handler.
@dodopayments/ingestion-blueprints provides trackers that make the usageEvents.ingest call for you, including the LLM Blueprint, API gateway, object storage, streams, and time-range usage.
4

How Deductions Happen

The server never calls a “deduct N credits” endpoint. The meter does the deduction:
  1. Your handler calls OpenAI and reads usage.total_tokens, for example 1532.
  2. You ingest one usage event with event_name: api.tokens_used and metadata: { tokens: 1532 }.
  3. The Token Usage Meter aggregates events per customer. A background worker processes new events every minute.
  4. Because the meter bills the API Tokens credit through Bill usage in credits, Dodo Payments deducts 1532 credits, starting with the customer’s grant that expires first (FIFO).
  5. If overage is enabled and the balance runs out, the deficit is tracked and billed on the next invoice.
Your code only ingests events.

Step 6: Add a Demo Frontend

Create public/index.html to test every flow in your browser. The page saves the customer ID in localStorage, so subscribe, generate, and top-up share one identity, as they would in a logged-in app:

Step 7: Wire Up the Webhook

Webhooks let your server react to balance changes, for example to email a customer whose balance is running low.
1

Expose Your Local Server

Webhooks need a public URL. For local development, use ngrok or another tunnel:
Copy the HTTPS forwarding URL, which ends in ngrok-free.app.
2

Register the Webhook in Dodo Payments

  1. In the dashboard, go to Developer → Webhooks and click Add endpoint.
  2. Enter the URL https://your-tunnel.ngrok-free.app/webhooks/dodo, using your own tunnel host.
  3. Select at least these events:
    • credit.added
    • credit.deducted
    • credit.overage_charged
  4. Click Create endpoint, then copy the signing secret from the endpoint’s Overview tab.
  5. Paste it into .env as DODO_PAYMENTS_WEBHOOK_KEY, then restart npm run dev.
The SDK’s dodo.webhooks.unwrap() checks the webhook-id, webhook-timestamp, and webhook-signature headers with your signing secret, then parses the payload. Don’t write your own HMAC check: Dodo Payments follows Standard Webhooks, which signs id.timestamp.body, not the body alone.

Step 8: Test the Full Flow

1

Subscribe a Test Customer

  1. Run npm run dev.
  2. Open http://localhost:3000.
  3. Pick Pro, enter a test email address and name, and click Get Checkout Link. Complete checkout with test card details.
  4. In the dashboard, go to Customers, open the newest customer, and copy its ID, which starts with cus_.
  5. Paste the ID into the Logged-in customer ID field on the demo and click Save.
The customer has 40,000,000 tokens. Click Refresh Balance to confirm.
2

Generate an AI Response

Type a prompt and click Generate. The server calls OpenAI, reads the actual total_tokens, ingests a usage event, and returns the response.
A background worker processes usage events every minute, so the balance doesn’t drop right away. Wait a minute or two, then click Refresh Balance again. An unchanged balance on the first refresh doesn’t mean metering failed.
3

Test the Top-Up Flow

Click Buy 5M Tokens — $19 and complete checkout. After the payment succeeds, refresh the balance: it increases by 5,000,000 tokens, and the server log shows a credit.added event.

Troubleshooting

Possible causes:
  • The meter’s event name doesn’t match the event_name you send. api.tokens_used is case-sensitive.
  • The meter isn’t linked to the API Tokens credit on the product. Open the product’s meter configuration and confirm Bill usage in credits is on.
  • The metadata.tokens key doesn’t match the meter’s Over Property.
  • The customer’s grant has expired. Check the customer’s credit history.
What to check:
  1. In Products → Meters, open the meter and confirm the product attachment shows the linked credit name.
  2. Open the meter’s Events tab. Ingested events appear there even before any deduction.
  3. Open the customer in Customers and select the Credits tab. Ledger entries appear within a minute or two.
Possible causes:
  • The customer hasn’t completed checkout. Credits are issued only after a successful payment.
  • You’re querying with the wrong customer_id. Use the ID that starts with cus_ from the dashboard, not an ID from your own database.
  • CREDIT_ENTITLEMENT_ID in .env doesn’t match the credit attached to the product.
What to check: Open the customer in Customers and select the Credits tab. If no credits appear, the credit wasn’t attached to the product or the payment didn’t complete.
Possible causes:
  • Overage isn’t enabled on the Pro product’s credit attachment. The setting on the credit is only a default.
  • The customer is on Starter, not Pro.
  • Overage Limit is set to 0.
What to check: Edit the Pro product, open the credit in Entitlements, and confirm Allow Overage is on and Price Per Unit is 0.000005 ($5 per million tokens). Check the leading zeros: the field takes a price per token, not per 1K tokens.
Possible causes:
  • Body parsing order: express.json() ran on /webhooks/dodo before express.raw(). The SDK needs the raw bytes of the request, not parsed JSON.
  • DODO_PAYMENTS_WEBHOOK_KEY holds the wrong signing secret.
  • A reverse proxy rewrites the request headers.
What to check: Confirm that the app.use('/webhooks/dodo', express.raw(...)) line comes before app.use(express.json()) in server.ts.

Need Help?

Congratulations! You’ve Built Credit-Based Billing for NeuralAPI

NeuralAPI now bills in credits from checkout to deduction:

Token Credit Entitlement

A reusable API Tokens credit with a 30-day expiry, shared by both plans and the top-up pack.

Tiered Plans, One Credit

Starter (10M tokens, hard limit) and Pro (40M tokens plus overage), configured per product without duplicating the credit.

One-Time Top-Up Pack

Customers add 5M tokens for $19 without changing their subscription.

Deduction Through a Meter

Actual OpenAI token counts are ingested as events, and the meter deducts credits FIFO with no manual tracking.

Live Balance API

The current balance, read through the SDK, to gate access, show usage, or warn customers in your app.

Verified Webhook Pipeline

Credit ledger events (credit.added, credit.deducted, credit.overage_charged) routed through a handler that verifies signatures with the SDK’s Standard Webhooks helper.
Going to production? Tighten these:
  • Add authentication to /credits/:customerId and /api/generate. As written, anyone can call them with any customer ID. Authenticate users and look up their customer ID on the server.
  • Use stable event_id values. The example uses Date.now() plus a random string. In production, use your request ID so that retries are idempotent: Dodo Payments ignores an event whose event_id it has already ingested.
  • Store the customer-to-user mapping. Save customer_id in your database after the first checkout, so users don’t paste it manually.
  • Decide what happens when a subscription ends. Plan credits stay in the customer’s ledger until they expire 30 days after issuance, and top-up credits stay valid for 365 days. The tutorial’s /api/generate checks only the balance, not the subscription status, so a cancelled customer can still use their remaining tokens. That’s the customer-friendly default. For stricter access, either (a) listen for the subscription.cancelled webhook and gate /api/generate on subscription status, or (b) on cancellation, debit the unused plan credits with the ledger API. Debits draw from the grant that expires first, so the 30-day plan credits go before the 365-day top-up credits.
  • Monitor the Usage Billing dashboard to catch metering anomalies early.

Credit-Based Billing Reference

Rollover, overage modes, ledger management, and every credit API endpoint.

Credit Webhook Events

Payload schemas for every credit event your server can receive.
Last modified on September 26, 2026