Credyt integration guide for AI assistants and tools
This guide helps AI assistants (like ChatGPT, Claude, Lovable, and other AI and vibe coding tools) walk developers through integrating Credyt into their applications.
Credyt is real-time billing infrastructure built for AI products. It handles usage-based billing, prepaid wallets, and revenue recognition, so you don't have to build it yourself.
⚠️ CRITICAL: READ THIS FIRST ⚠️
STOP. Do not write any code yet.
When a user asks you to integrate Credyt, your response must follow this order:
- ❌ DO NOT write code
- ❌ DO NOT create files
- ❌ DO NOT assume a billing model
- ✅ DO ask discovery questions (one at a time)
- ✅ DO explain billing models with examples from their domain
- ✅ DO help them define products in Credyt
- ✅ ONLY THEN write integration code
If you write code before understanding their business model, you are doing it wrong.
This is not optional. Discovery must come first.
Required integration workflow
Follow these steps in order. Do not skip ahead.
Phase 1: Discovery (REQUIRED FIRST)
Ask questions one at a time. Listen to answers. Explain concepts with concrete examples.
Goals:
- Understand their business model
- Choose billing model (usage-based, subscription, or hybrid)
- Decide fiat currency vs custom assets
- Identify billable events
- Define pricing dimensions
Do not proceed until you understand their monetization strategy.
Phase 2: Product definition (REQUIRED SECOND)
Help them create product configuration in Credyt.
This happens via API calls OR the Credyt dashboard. Either way, products must be defined before you write integration code.
Goals:
- Create custom assets (if needed)
- Create products with pricing
- Configure event types
- Set up dimensional pricing (if needed)
Phase 3: Code integration (ONLY AFTER PHASES 1-2)
Now you can write code.
Create backend integration, implement wallet checks, send usage events, handle top-ups.
Common mistakes to avoid
❌ WRONG:
User: "Integrate Credyt into my image generation app"
AI: *immediately writes code with $0.50 per image hardcoded*
✅ RIGHT:
User: "Integrate Credyt into my image generation app"
AI: "Before I write any code, I need to understand your business model.
How do you want to charge for image generation?"
❌ WRONG: Asking 10 questions at once in a massive list
✅ RIGHT: Ask questions sequentially, adapting based on previous answers
❌ WRONG: Assuming they want usage-based pricing
✅ RIGHT: Explaining all three models with examples from their domain
Pre-code checklist
Complete ALL of these before writing any code:
- Asked about billable activities (what costs them money)
- Asked about pricing preferences (how they want to charge)
- Asked about ability to front costs (can they absorb usage before payment)
- Explained all three billing models with domain-specific examples
- User has chosen a billing model
- Decided fiat vs custom assets (with clear reasoning)
- Identified all billable event types
- Defined pricing dimensions (if applicable)
- Helped create products in Credyt (API or dashboard)
- Confirmed product configuration is complete
Only proceed to code when ALL boxes are checked.
Before you start
When a user asks to integrate Credyt, you MUST start by understanding their business model.
Do not proceed to code without completing discovery. This is not optional.
Don't write code yet. Start with questions. Ask them sequentially, one at a time, adapting based on their answers.
Read these first:
Note: If HTML docs don't load, append
.mdto the URL (e.g.,https://docs.dev.credyt.ai/advanced-topics/refunds.md) to get the markdown version.
Discovery: Understand their monetization
Before you write code, understand how they make money.
How to ask questions:
- Ask questions ONE AT A TIME
- Listen to their answer before asking the next question
- Adapt follow-up questions based on what they tell you
- Never dump 5+ questions on them at once
Question order matters:
- Start with billing model (affects everything else)
- Then fiat vs custom assets (if needed)
- Then specific billable events
- Then pricing dimensions
- Finally account setup
Each answer informs the next question. This is a conversation, not a form.
1. Choose a billing model
Help them pick between three models. Each solves different problems.
Start by explaining what these models actually mean with concrete examples from their domain.
Real-time usage-based billing (prepaid)
Customers add funds upfront. Usage draws down the balance in real time. When the balance hits zero, service stops or triggers automatic refill.
What this means in practice:
- Charge users for activities they perform in your app
- Examples: $0.03 per API call, $2.50 per video generated, $0.001 per token
- Like a prepaid phone: add $20, make calls, balance decreases with each call
How others do it:
- OpenAI: charges per token consumed (e.g., $0.002 per 1K tokens for GPT-4)
- Replicate: charges per second of model compute time
- ElevenLabs: charges per character of audio generated
This works when:
- Infrastructure costs are variable and unpredictable
- You can't afford to front costs for customers
- Your customers expect pay-as-you-go pricing
- You need cash flow protection
Example question for user: "If you charge $0.10 per image your app generates, would customers prepay (like adding $10 for 100 images) or get billed monthly for what they used?"
Fixed recurring fees (aka traditional SaaS subscriptions)
Customers pay a fixed amount per billing cycle. This provides baseline revenue while you figure out usage pricing.
What this means in practice:
- Charge a flat monthly or annual fee
- Examples: $20/month for Pro access, $99/year for Premium features
- Like Netflix: pay $15/month regardless of how much you watch
How others do it:
- Most traditional SaaS: Slack, Notion, Figma charge per seat per month
- GitHub: $4/user/month for team features
This works when:
- You need revenue now but aren't ready to price usage
- You want to understand cost structure before charging for usage
- You're planning to transition to usage-based pricing later
- Enterprise customers require predictable billing cycles
Start here if you're still validating product-market fit. Track usage and costs without charging for them yet. Use profitability data to inform your eventual usage pricing.
Example question for user: "Do you want to charge users a fixed monthly fee for access to your app, regardless of how much they use it?"
Hybrid (subscriptions + entitlements + top-ups)
Base subscription includes usage allowances. Additional usage is purchased through top-ups or charged as overages.
What this means in practice:
- Monthly subscription that includes a credit allowance
- Examples: $20/month includes 1,000 credits, extra credits are $0.05 each
- Like a phone plan: $30/month includes 5GB data, pay $10/GB for overages
How others do it:
- Clay: monthly subscription includes credit allocation for data enrichment
- Cursor: different tiers include different amounts of AI completions
- GitHub Copilot: subscription with usage caps, then throttling or upgrades
This works when:
- You need baseline recurring revenue plus usage-based growth
- Some features are seat-based, others consumption-based
- Customers want predictability with flexibility for overages
- Different customer segments expect different billing approaches
Example question for user: "Would you want to give users 1,000 free credits per month with their $20 subscription, then charge them $0.05 per credit when they run out?"
Start with this question: "How do you want to charge for [their specific activity]?"
Then adapt based on their answer. If they say "per image" → usage-based. If they say "monthly fee" → subscription. If they say "both" → hybrid.
Follow-up questions (ask based on context):
- "What activities in your app should be billable?" (be specific: API calls, images generated, minutes of video, tokens processed)
- "How do you want to charge for those activities?" (give pricing examples: $0.10 per image, $2.50 per video, $0.001 per token)
- "Can you afford to front infrastructure costs?" (explain: if a user generates a $5 video but hasn't paid yet, can you absorb that cost?)
- "How predictable is customer usage?" (explain: some customers might use 10x more than others in the same month)
- "What do similar products charge?" (help them research: look at OpenAI, Anthropic, Replicate, etc.)
2. Fiat currency vs custom assets (critical decision)
One of the most important decisions: price in dollars or custom units?
This choice affects how customers perceive value, how you handle pricing changes, and whether you can offer earning mechanisms.
Price in fiat currency (USD, EUR) when:
Your costs are deterministic per unit. Customers are technical users who understand infrastructure metrics. The unit-to-value relationship is already clear.
Examples:
- OpenAI and Anthropic price in tokens but show dollar balances. Technical users understand that 10M tokens through GPT-4 has a clear cost.
- Replicate charges per second of compute time, billed in dollars.
Advantages:
- Transparent pricing (customers see exactly what they pay)
- No conversion confusion
- Simpler accounting
- Enterprise-friendly (matches procurement expectations)
Price in custom units (credits, tokens, minutes) when:
Infrastructure costs vary but customer-facing pricing should stay predictable. Non-technical users need product-native units. You expect pricing to evolve as you learn unit economics.
What this means:
- Video platforms: Bill in "video minutes" not dollars
- Translation apps: Bill in "words" or "document credits" not tokens
- Voice platforms: Bill in "characters" or "conversation minutes"
- Gaming: Bill in "coins" or "gems" that can be earned and spent
Why Midjourney uses GPU hours: Midjourney allocates GPU time to subscribers (3.3 hours Basic, 15 hours Standard, 30 hours Pro). The actual GPU cost per image varies by model, resolution, and settings. Customers see consistent GPU time deductions. Infrastructure complexity is abstracted.
Different models: Gen-4 costs more compute than Gen-4 Turbo. Customers pay in GPU time, not variable per-image costs. When infrastructure costs change, the GPU hour price can adjust without confusing customers.
Why Runway uses credits: Runway bills video generation in credits. Gen-4 costs 12 credits/second, Gen-4 Turbo costs 5 credits/second. Different quality tiers have different computational requirements. Customers see predictable credit deductions. The relationship between credits and value stays stable even as underlying costs shift.
Three problems custom assets solve:
1. Infrastructure costs vary, pricing shouldn't
AI platforms face unpredictable compute costs. Quality settings, duration, complexity all affect cost. If you bill directly for infrastructure, pricing becomes unpredictable. If you average costs, margins erode on expensive requests.
Custom units decouple infrastructure variance from customer-facing pricing. A standard job costs 1 credit, high-quality costs 2 credits, priority costs 3 credits. Infrastructure scales invisibly.
2. Product-native units make sense
When you bill in dollars, customers see "$1.47" without understanding what they purchased. When you bill in video minutes, they see "Generated 4-second clip: -2 minutes." Usage history shows exactly what was consumed in units that map to behavior.
Translation apps: A non-technical user being billed in LLM tokens has no reference. But "words" or document credits (small, medium, large) make immediate sense.
3. Value can be earned, not just purchased
Credits become powerful when customers can earn them outside purchases.
Lovable lets users earn credits through referrals: 10 credits when someone signs up through your link, 10 more when they publish their first app. These credits work identically to purchased credits.
Gaming platforms use gems, coins, tokens. Players purchase bundles but also earn currency through gameplay, achievements, daily bonuses. This enables hybrid monetization: some users pay, others earn, most do both.
When credits can be earned through product engagement, they stop being purely transactional and become part of the product experience.
Start by asking: "Do you want customers to see prices in dollars (like $2.50 per video) or in credits/tokens (like 10 credits per video)?"
Listen to their answer. Then ask follow-up questions based on what they need help with:
If they're unsure, ask one of these:
- "Do your infrastructure costs vary significantly based on usage complexity?"
- "Are your users technical (understand tokens/API calls) or non-technical (need simpler units)?"
- "Do you want customers to earn credits through referrals or engagement?"
- "Will your pricing likely change as you learn unit economics?"
- "Would customers benefit from seeing 'video minutes' vs '$0.15 per generation'?"
If choosing custom assets, they'll need to create these first (before products). See Step 2 in Implementation for the technical setup.
3. Identify billable events
Help them identify what consumes resources or delivers value.
Start with: "What activities in your app cost you money to provide?"
Listen to their answer. Then dig deeper with specific follow-ups:
Follow-up questions (based on their answer):
- "What actions cost you money?"
- "What outcomes can you measure?"
- "What events are expensive to process?"
Common event types:
- API calls
- AI model completions (chat, images, video)
- Processing time (minutes, seconds)
- Volume consumed (tokens, data, storage)
- Quality tiers (standard, premium)
- Speed tiers (fast, regular)
Best practice: Send usage events for all meaningful activities initially. Review them in Credyt. Decide pricing later.
4. Pricing dimensions
Does pricing vary based on attributes? This is dimensional pricing.
Ask: "Do you charge different amounts based on quality, speed, or model type?"
If yes, ask for specifics: "What are the different tiers and how should they be priced?"
Common dimensions:
- "Do different AI models cost different amounts?"
- "Do you charge more for faster processing?"
- "Are there quality tiers with different prices?"
These attributes become billable dimensions in Credyt.
5. Account setup
Ask: "Do you have a Credyt account set up already?"
If no:
- Sign up at https://app.credyt.ai/api/sign-up
- Accounts start in test mode (perfect for integration)
- Get API keys from https://app.credyt.ai (Developers section)
If yes:
- Confirm they have their test API key
- Remind them: server-side only, never in client code
- Ask: "Do you have your API key handy?"
Discovery checkpoint
Before moving to implementation, confirm you have:
✅ Clear billing model chosen (usage-based, subscription, or hybrid)
✅ Fiat or custom assets decision made
✅ All billable events identified
✅ Pricing structure defined (including dimensions if applicable)
✅ Credyt account set up with API keys
If any of these are unclear, go back and ask more questions.
Only proceed to Implementation once discovery is complete.
Implementation
Once you understand their model, walk them through these steps.
Important: If they want to use custom assets (tokens, credits, coins), create those FIRST before creating products or processing transactions. Custom assets must exist before they can be referenced in product pricing or wallet adjustments.
Step 1: Set up authentication
All API requests require the X-CREDYT-API-KEY header.
Security rules:
- Store API keys server-side only
- Never expose keys in client code
- Use environment variables
// .env file
CREDYT_API_KEY = your_test_api_key_here;
// API client
const headers = {
"Content-Type": "application/json",
"X-CREDYT-API-KEY": process.env.CREDYT_API_KEY,
};
Test your connection:
Verify your API key works by listing customers:
const response = await fetch("https://api.credyt.ai/customers", { headers });
if (response.ok) {
console.log("✓ Connected to Credyt successfully");
} else {
console.error("✗ Authentication failed - check your API key");
}
This endpoint always succeeds if you're authenticated correctly.
Step 2: Define products and pricing
Products define what you bill for and how. You typically create these once during setup—not in your application code.
Workflow order (important):
- Create custom assets first (if using tokens, credits, etc.)
- Then create products that reference those assets
- Subscribe customers to products
Core concepts:
- Product: What the customer consumes (e.g., "Video Generation")
- Price: One product can have multiple prices for different events
- Event type: The billable action (e.g.,
video_generated,message_completed) - Usage type:
unit- charge per occurrencevolume- charge based on quantity in payloadunit_and_volume- both
Publishing products:
Products must be published before customers can subscribe to them. Set publish: true when creating the product, or publish it later using PATCH /products/:productId/:version.
If using custom assets (tokens, credits, coins)
Create these BEFORE creating products. Custom assets must exist before they can be referenced.
// Step 1: Create the custom asset
const asset = {
code: "CREDIT",
name: "Credits",
precision: 0,
symbol: "⭐",
label: "CR",
rates: [
{
source: "USD",
rate: 0.05, // $0.05 per credit (or $1 = 20 credits)
},
],
};
await fetch("https://api.credyt.ai/assets", {
method: "POST",
headers,
body: JSON.stringify(asset),
});
// Step 2: Now create products that use this asset
const product = {
name: "AI Image Generation",
code: "image_gen_std",
prices: [
{
name: "Image Generation",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "image_generated",
usage_type: "unit",
},
pricing: [
{
asset: "CREDIT", // References the asset we just created
values: [{ unit_price: 10 }], // 10 credits per image
},
],
},
],
publish: true, // Publish immediately so customers can subscribe
};
await fetch("https://api.credyt.ai/products", {
method: "POST",
headers,
body: JSON.stringify(product),
});
If using fiat currency (USD, EUR)
You can skip asset creation and create products directly.
Unit-based pricing
Charge per occurrence. Here we charge $2.50 per video generation:
const product = {
name: "AI Video Generation",
code: "video_gen_std",
prices: [
{
name: "Video Generation",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "video_generated",
usage_type: "unit",
source_reference_field: "video_id",
},
pricing: [
{
asset: "USD",
values: [{ unit_price: 2.5 }],
},
],
},
],
publish: true,
};
const response = await fetch("https://api.credyt.ai/products", {
method: "POST",
headers,
body: JSON.stringify(product),
});
Volume-based pricing
Charge based on quantity consumed. Here we charge $0.001 per token:
const product = {
name: "AI Chat Service",
code: "chat_service_std",
prices: [
{
name: "Token Usage",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "message_completed",
usage_type: "volume",
volume_field: "total_tokens",
source_reference_field: "chat_id",
},
pricing: [
{
asset: "USD",
values: [{ volume_rate: 0.001 }],
},
],
},
],
publish: true,
};
await fetch("https://api.credyt.ai/products", {
method: "POST",
headers,
body: JSON.stringify(product),
});
Dimensional pricing
Different rates based on attributes. Here we charge different rates per model:
const product = {
name: "Multi-Model Chat",
code: "chat_multimodel",
prices: [
{
name: "Token Usage",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "message_completed",
usage_type: "volume",
volume_field: "total_tokens",
billable_dimensions: ["model"], // This is the key for dimensional pricing
},
pricing: [
{
asset: "USD",
values: [
{
name: "GPT-4 Tokens",
dimensions: { model: "gpt-4" },
values: [{ volume_rate: 0.03 }],
},
{
name: "GPT-3.5 Tokens",
dimensions: { model: "gpt-3.5" },
values: [{ volume_rate: 0.001 }],
},
],
},
],
},
],
publish: true,
};
Step 3: Create customers
Register customers before billing them. Subscribe them to the products they use.
Key points:
- Use
external_idto link the Credyt customer to your system's user ID or auth identity - Subscribe customers to products they'll use
- Wallets are created automatically
- Handle the case where customer already exists (422 error)
const customer = {
name: "Jane Developer",
external_id: "user_12345", // Your database user ID or auth provider ID (e.g., Auth0, Clerk)
subscriptions: [
{
products: [
{
code: "video_gen_std", // Product code from Step 2
version: "default", // or specific version number
},
],
},
],
};
const response = await fetch("https://api.credyt.ai/customers", {
method: "POST",
headers,
body: JSON.stringify(customer),
});
if (response.ok) {
const { id: credytCustomerId } = await response.json();
// Store this ID in your database alongside your user record
console.log("Customer created:", credytCustomerId);
} else if (response.status === 422) {
// Customer with this external_id already exists
const error = await response.json();
if (error.errors?.external_id) {
console.log("Customer already exists, looking up by external_id...");
// Look up existing customer
const lookup = await fetch(
`https://api.credyt.ai/customers?external_id=user_12345`,
{ headers },
);
const existingCustomer = await lookup.json();
console.log("Found existing customer:", existingCustomer.id);
}
} else {
console.error("Failed to create customer:", await response.text());
}
Using external IDs in API calls:
You can use your external ID directly when sending usage events, by specifying the customer_external_id instead:
const usageEvent = {
customer_external_id: "user_12345", // Your ID for the customer
events: [
/* ... */
],
};
await fetch("https://api.credyt.ai/events", {
method: "POST",
headers,
body: JSON.stringify(usageEvent),
});
For other API calls, you need the Credyt customer ID. You can look it up by external ID:
// Look up Credyt ID from your external ID
const response = await fetch(
"https://api.credyt.ai/customers?external_id=user_12345",
{ headers },
);
const customer = await response.json();
const credytCustomerId = customer.id;
// Now use Credyt ID for wallet operations, etc.
await fetch(`https://api.credyt.ai/customers/${credytCustomerId}/wallet`, {
headers,
});
Best practice: Store the Credyt customer ID in your database alongside your user record. This avoids the lookup call on every request.
Step 4: Fund customer wallets
Customers need balance before usage can be billed.
You have four options.
Option A: Billing portal (self-service)
Easiest option. Customers manage their own top-ups through Credyt's hosted portal.
What customers can do:
- View balances and usage
- Add funds via Stripe
- Configure auto top-up
- See transaction history
No sign-up required.
// Generate a billing portal session
const session = {
customer_id: credytCustomerId,
return_url: "https://yourapp.com/account",
failure_url: "https://yourapp.com/billing-error",
};
const response = await fetch(`https://api.credyt.ai/billing-portal/sessions`, {
method: "POST",
headers,
body: JSON.stringify(session),
});
const { redirect_url } = await response.json();
// Redirect customer to redirect_url
// Link expires in 10 minutes
Option B: Top-up API (your UI + Credyt payments)
Use when you want top-ups in your own UI but use Credyt's payment processing.
const topup = {
customer_id: credytCustomerId,
amount: 25.0,
currency: "USD",
description: "Account credit",
return_url: "https://yourapp.com/account",
failure_url: "https://yourapp.com/payment-failed",
};
const response = await fetch(`https://api.credyt.ai/top-ups`, {
method: "POST",
headers,
body: JSON.stringify(topup),
});
const { redirect_url } = await response.json();
// Redirect to Stripe Checkout
Option C: External PSP + Adjustments (your payment processing)
Use when you handle payments through your own payment provider.
After successful payment in your PSP:
const adjustment = {
transaction_id: "unique-uuid-or-payment-id",
asset: "USD",
amount: 25.0,
reason: "external_topup",
metadata: {
psp: "stripe",
payment_intent: "pi_abc123",
},
};
await fetch(
`https://api.credyt.ai/customers/${credytCustomerId}/wallet/adjustments`,
{
method: "POST",
headers,
body: JSON.stringify(adjustment),
},
);
Option D: Pre-fund for testing (development only)
Quick way to add balance during development. No payment flows needed.
const adjustment = {
transaction_id: crypto.randomUUID(),
asset: "USD",
amount: 100.0,
reason: "external_topup",
metadata: { note: "Test funding" },
};
await fetch(
`https://api.credyt.ai/customers/${credytCustomerId}/wallet/adjustments`,
{
method: "POST",
headers,
body: JSON.stringify(adjustment),
},
);
Step 5: Check balances
Check wallet balances before allowing billable actions. This is the typical pattern.
Best practice: Check balance first, then authorize the action, then send usage.
Get entire wallet:
const response = await fetch(
`https://api.credyt.ai/customers/${credytCustomerId}/wallet`,
{ headers },
);
const { accounts } = await response.json();
// accounts = [
// { id: "default:USD", asset: "USD", available: 14.56 },
// { id: "default:TOKENS", asset: "TOKENS", available: 5000 }
// ]
Get specific account:
const response = await fetch(
`https://api.credyt.ai/customers/${credytCustomerId}/wallet/default:USD`,
{ headers },
);
const account = await response.json();
// {
// id: "default:USD",
// asset: "USD",
// available: 14.56,
// pending_in: 0,
// pending_out: 0.5
// }
Implementation pattern:
async function canPerformAction(customerId, estimatedCost) {
const wallet = await fetch(
`https://api.credyt.ai/customers/${customerId}/wallet`,
{ headers },
);
const { accounts } = await wallet.json();
const usdAccount = accounts.find((a) => a.asset === "USD");
if (!usdAccount || usdAccount.available < estimatedCost) {
return {
allowed: false,
message: "Insufficient balance. Please top up your account.",
currentBalance: usdAccount?.available || 0,
};
}
return { allowed: true };
}
// Usage
app.post("/api/generate-video", async (req, res) => {
const customerId = req.user.credytCustomerId;
const estimatedCost = 2.5; // $2.50 per video
// 1. Check balance first
const check = await canPerformAction(customerId, estimatedCost);
if (!check.allowed) {
return res.status(402).json({ error: check.message });
}
// 2. Perform the action (generate video)
const video = await generateVideo(req.body);
// 3. Send usage event to bill
await sendUsage(customerId, "video_generated", { video_id: video.id });
res.json({ videoId: video.id });
});
Step 6: Send usage events
After confirming balance, perform the action and send usage events. Billing happens in real time.
Requirements:
- Each event needs a unique
id(idempotency key) event_typemust match a product's usage calculation- Include either the Credyt Customer ID (
customer_id) or your external ID (customer_external_id)
Unit-based (charge per occurrence)
const usageEvent = {
customer_external_id: "user_12345",
events: [
{
id: crypto.randomUUID(), // Unique ID for idempotency
event_type: "video_generated",
occurred_at: new Date().toISOString(),
subject: "video_abc123", // Reference to the generated video
description: "AI video generation completed",
data: {
video_id: "video_abc123", // Matches source_reference_field
},
},
],
};
await fetch("https://api.credyt.ai/events", {
method: "POST",
headers,
body: JSON.stringify(usageEvent),
});
Volume-based (charge based on quantity)
const usageEvent = {
customer_id: credytCustomerId,
events: [
{
id: crypto.randomUUID(),
event_type: "message_completed",
occurred_at: new Date().toISOString(),
subject: "chat_session_456",
description: "Chat completion",
data: {
chat_id: "chat_session_456",
total_tokens: 1500, // Must match volume_field in product config
input_tokens: 500,
output_tokens: 1000,
},
},
],
};
Dimensional (pricing varies by attribute)
const usageEvent = {
customer_id: credytCustomerId,
events: [
{
id: crypto.randomUUID(),
event_type: "message_completed",
occurred_at: new Date().toISOString(),
subject: "chat_xyz",
description: "GPT-4 chat",
data: {
chat_id: "chat_xyz",
total_tokens: 2000,
model: "gpt-4", // Billable dimension - matches product config
},
},
],
};
Advanced topics
Custom assets implementation
If you decided to use custom assets (see Discovery section 2), the implementation is covered in Step 2 of the Implementation guide above.
Quick reminder of the workflow:
- Create custom asset first (e.g., COINS, CREDITS, MINUTES)
- Create products that price in that asset
- Grant credits via Adjustments API or let customers purchase via top-ups
Auto top-up
Customers configure automatic refills via the Billing Portal.
Set a threshold (e.g., when balance drops below $10) and a refill amount (e.g., add $50). Each asset can have its own configuration. Requires a saved payment card.
Testing payments
Test mode:
- All new accounts start in test mode
- Use Stripe test card:
4242 4242 4242 4242 - More test cards: https://docs.stripe.com/testing
Going live:
- Switch account to live mode in Credyt Portal
- Connect production Stripe account (if using Credyt payments)
- Update API key to live key
Hybrid billing (subscriptions + entitlements)
Credyt supports native hybrid billing that combines recurring subscriptions with bundled credit entitlements.
How it works:
Customers pay a monthly subscription fee and receive a credit allowance each billing cycle. When they exceed their included credits, they purchase additional credits or pay overage fees.
Example: "$20/month includes 1,000 credits"
Create a custom asset for credits:
const asset = {
code: "CREDIT",
name: "Credits",
precision: 0,
symbol: "⭐",
label: "CR",
rates: [
{
source: "USD",
rate: 0.05, // $0.05 per credit (or $1 = 20 credits)
},
],
};
await fetch(`https://api.credyt.ai/assets`, {
method: "POST",
headers,
body: JSON.stringify(asset),
});
Create hybrid product with entitlements:
const product = {
name: "Premium Plan",
code: "premium_monthly",
entitlements: [
{
name: "Monthly Credit Allowance",
asset: "CREDIT",
amount: 1000, // 1,000 credits included
purpose: "bundled",
refresh: {
interval: "month",
strategy: "expire_and_replace", // Unused credits don't roll over
},
accounting: {
revenue_basis: 0, // Revenue from subscription fee
cost_basis: "auto",
},
},
],
prices: [
{
name: "Monthly Subscription Fee",
type: "fixed",
billing_model: {
type: "recurring",
recurring: { interval: "month" },
},
pricing: [
{
asset: "USD",
values: [{ unit_price: 20 }],
},
],
},
{
name: "Image Generation",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "image_generated",
usage_type: "unit",
},
pricing: [
{
asset: "CREDIT",
values: [{ unit_price: 10 }], // 10 credits per image
},
],
},
],
publish: true,
};
How consumption works:
- Customer pays $20/month
- Receives 1,000 credits monthly
- Each image costs 10 credits (can generate 100 images)
- When credits run out, they purchase more at $0.05/credit
- Credits expire each month (no rollover)
Subscribe customers:
const customer = {
name: "Jane Developer",
external_id: "user_12345",
email: "jane@example.com",
subscriptions: [
{
products: [{ code: "premium_monthly" }],
},
],
};
const response = await fetch(`https://api.credyt.ai/customers`, {
method: "POST",
headers,
body: JSON.stringify(customer),
});
const data = await response.json();
// Check if payment is required
if (data.subscriptions[0].status === "pending") {
const redirectUrl = data.subscriptions[0].required_actions.find(
(a) => a.type === "payment",
).redirect_url;
// Redirect customer to complete payment
}
Credyt handles billing cycles, credit grants, and consumption tracking automatically.
Using external PSP for subscriptions:
If you process subscriptions through your own payment provider, reflect payments in Credyt using Adjustments:
// When subscription payment succeeds in your PSP:
const adjustment = {
transaction_id: `sub_payment_${subscriptionId}`,
asset: "USD",
amount: 29.99,
reason: "external_topup",
description: "Monthly subscription",
};
await fetch(
`https://api.credyt.ai/customers/${customerId}/wallet/adjustments`,
{
method: "POST",
headers,
body: JSON.stringify(adjustment),
},
);
Then send usage events as normal. They deduct from the wallet balance.
Refunds
Credyt doesn't handle refunds automatically.
Process:
- Process refund in your PSP (or Stripe if using Credyt payments)
- Notify Credyt via Adjustments API
const refund = {
transaction_id: `refund_${originalPaymentId}`,
asset: "USD",
amount: -20.0, // Negative amount
reason: "external_refund",
description: "Refund for technical issue",
};
await fetch(
`https://api.credyt.ai/customers/${customerId}/wallet/adjustments`,
{
method: "POST",
headers,
body: JSON.stringify(adjustment),
},
);
Cost tracking (profitability)
Track infrastructure costs alongside revenue.
const usageEvent = {
customer_id: customerId,
events: [
{
id: crypto.randomUUID(),
event_type: "video_generated",
occurred_at: new Date().toISOString(),
subject: "video_123",
description: "Video generation",
data: {
minutes: 2,
model: "sora-fast",
},
costs: [
{
// Optional cost tracking
id: crypto.randomUUID(),
vendor_external_id: "vnd_openai_123",
description: "OpenAI Sora API",
amount: 0.16,
currency: "USD",
metadata: {
model: "sora-fast",
resolution: "1080p",
},
},
],
},
],
};
Credyt will calculate profitability metrics (gross revenue, costs, net revenue, margin).
Standalone wallets (in-app economies)
Credyt's wallet API works for in-app economies where users earn and spend points without traditional payments.
Common use cases:
- Game currencies where players earn coins through gameplay
- Reward programs where users accumulate points
- Community platforms with reputation or karma systems
- Referral programs that grant credits
Critical: Create your custom asset (COINS, POINTS, etc.) BEFORE granting credits or creating products. See Step 2 for how to create assets.
Setup (do this once):
// 1. Create the custom asset first
const asset = {
code: "COINS",
name: "Game Coins",
precision: 0,
symbol: "🪙",
label: "COINS",
rates: [
{
source: "USD",
rate: 0.01, // Not used if you never collect payments, but required
},
],
};
await fetch("https://api.credyt.ai/assets", {
method: "POST",
headers,
body: JSON.stringify(asset),
});
// 2. Create a product that prices items in coins
const product = {
name: "In-Game Items",
code: "game_items",
prices: [
{
name: "Power-Up Purchase",
type: "usage_based",
billing_model: { type: "real_time" },
usage_calculation: {
event_type: "item_purchased",
usage_type: "unit",
},
pricing: [
{
asset: "COINS",
values: [{ unit_price: 100 }], // 100 coins per item
},
],
},
],
publish: true,
};
await fetch("https://api.credyt.ai/products", {
method: "POST",
headers,
body: JSON.stringify(product),
});
When users earn coins (grant credits):
// User completes a quest - grant 500 coins
const adjustment = {
transaction_id: `quest_completed_${questId}_${userId}`,
asset: "COINS", // Must match the asset code you created
amount: 500,
reason: "gift",
description: "Quest completion reward",
};
await fetch(
`https://api.credyt.ai/customers/${customerId}/wallet/adjustments`,
{
method: "POST",
headers,
body: JSON.stringify(adjustment),
},
);
When users spend coins:
Send usage events that deduct from their balance.
const usageEvent = {
customer_id: customerId,
events: [
{
id: crypto.randomUUID(),
event_type: "item_purchased",
occurred_at: new Date().toISOString(),
subject: `purchase_${itemId}`,
description: "Power-up purchased",
data: {
item_id: itemId,
item_name: "Speed Boost",
},
},
],
};
await fetch("https://api.credyt.ai/events", {
method: "POST",
headers,
body: JSON.stringify(usageEvent),
});
This gives you a reliable balance system without building wallet infrastructure yourself.
Code Examples and Resources
Bruno API Collection
Interactive API examples available at:
- GitHub: https://github.com/credyt/learn/tree/main/bruno/credyt-api
- Download and import into Bruno (https://www.usebruno.com/)
Sample Integration Patterns
Express.js Middleware Example:
const credytClient = {
apiKey: process.env.CREDYT_API_KEY,
baseUrl: "https://api.credyt.ai",
async checkBalance(customerId) {
const response = await fetch(
`${this.baseUrl}/customers/${customerId}/wallet`,
{ headers: { "X-CREDYT-API-KEY": this.apiKey } },
);
return response.json();
},
async sendUsage(customerId, eventType, data) {
const event = {
customer_id: customerId,
events: [
{
id: crypto.randomUUID(),
event_type: eventType,
occurred_at: new Date().toISOString(),
subject: data.subject,
description: data.description,
data: data.payload,
},
],
};
return fetch(`${this.baseUrl}/events`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CREDYT-API-KEY": this.apiKey,
},
body: JSON.stringify(event),
});
},
};
// Middleware to check balance before expensive operations
async function requireSufficientBalance(req, res, next) {
const customerId = req.user.credytCustomerId;
const { accounts } = await credytClient.checkBalance(customerId);
const usdAccount = accounts.find((a) => a.asset === "USD");
if (!usdAccount || usdAccount.available < 1.0) {
return res.status(402).json({
error: "Insufficient balance",
balance: usdAccount?.available || 0,
topUpUrl: `/billing/top-up`,
});
}
next();
}
// Usage
app.post("/api/generate-video", requireSufficientBalance, async (req, res) => {
// Generate video...
// Bill for usage
await credytClient.sendUsage(req.user.credytCustomerId, "video_generated", {
subject: `video_${videoId}`,
description: "Video generation",
payload: { minutes: 2, quality: "hd" },
});
res.json({ videoId, status: "processing" });
});
Troubleshooting
Customer not billed for usage
Check:
- Is customer subscribed to a product? (
GET /customers/:id) - Does product have matching
event_type? - For volume pricing: does
volume_fieldmatch event data? - Is event ID unique? (Duplicates are ignored)
- Does customer have wallet balance?
Test without affecting balances:
const simulation = await fetch(
`https://api.credyt.ai/products/:productId/simulate`,
{
method: "POST",
headers,
body: JSON.stringify({
events: [
/* your test event */
],
}),
},
);
Negative balance
This is expected behavior. Credyt allows overdrafts by default so usage can complete without interruption.
Check balance according to your business logic. The next top-up automatically corrects the negative balance.
No wallet or accounts
Wallets are created automatically when:
- Customer is subscribed to a product, OR
- First top-up is initiated
Fix: Ensure customer has at least one product subscription.
Billing portal link expired
Links expire after 10 minutes. When expired, the customer is redirected to your return_url.
Best practice: Detect the redirect, generate a new session automatically, and redirect the customer back.
Key reminders
Security
- API keys are server-side only
- Never expose keys in client code
- Use environment variables
- Test mode and live mode use different keys
Testing
- Start in test mode (default for new accounts)
- Use Stripe test cards: https://docs.stripe.com/testing
- Pre-fund wallets with adjustments for quick testing
- Test the full flow before going live
Product design
- Define products once as setup (not per-request)
- Use
source_reference_fieldfor traceability - Include meaningful
subjectin usage events - Send usage for all activities initially, price later
Best practices
- Check balance before expensive operations
- Use idempotent event IDs (UUIDs)
- Store both Credyt customer ID and your external ID
- Monitor wallet balances to prevent service interruption
- Provide clear billing portal access for customers
Next steps
1. Connect Stripe (if using Credyt payments)
- Enables custom branding in checkout
- Allows tax configuration
- Required for production
2. Set up monitoring
- Track usage patterns
- Monitor wallet balances
- Review profitability metrics
3. Customize billing portal
- Add your branding
- Configure return URLs
- Test the customer experience
4. Plan for scale
- Consider auto top-up for power users
- Design balance notification system
- Plan for cost optimization
Getting Help
- Documentation: https://docs.dev.credyt.ai
- API Reference: https://docs.dev.credyt.ai/openapi/openapi.1.0.yaml
- Support: support@credyt.ai
- Examples: https://github.com/credyt/learn
Integration checklist
When guiding a user through Credyt integration:
- Understand their monetization model (usage-based, subscription, hybrid)
- Identify billable events and pricing dimensions
- Confirm Credyt account setup and API key access
- Define products and pricing configuration
- Create customers and subscriptions
- Implement wallet funding (portal, API, or external)
- Send usage events from application
- Check balances before billable actions
- Test complete flow in test mode
- Verify security (API keys server-side only)
- Plan production deployment (Stripe connection, live mode)