Jul 13, 2026

Embeddable payments SDK for AI apps: wallets, credits, and usage billing

Learn how to design an embeddable payments SDK for an AI app with credit wallets, secure browser sessions, usage debits, webhooks, idempotency, and cost reconciliation.

ENGINEERING11 min readThe Currai team / Engineering

TL;DR: An embeddable payments SDK for an AI app connects checkout to a durable credit ledger, then debits that ledger as users consume model-powered features. Keep payment secrets on the server, give the browser a short-lived scoped session, make every webhook and debit idempotent, and reconcile customer charges against the actual AI request that created them.

The hard part is not rendering a card form. It is preserving a correct balance when payment webhooks arrive twice, model calls fail halfway through, customers retry requests, refunds occur, and provider cost differs from the amount charged to the end user.

What is an embeddable payments SDK?

An embeddable payments SDK is a set of server APIs and frontend components that lets another application sell credits or usage without sending the user to a separate billing product. In an AI app, it typically combines hosted payment collection, a customer wallet, usage metering, configurable markup, and a ledger that explains every balance change.

The payment provider should collect card or bank details through its hosted elements. Your SDK owns the product-specific layer around that payment:

  • Which application user owns the wallet.
  • How money converts into credits.
  • Which AI models or features can consume those credits.
  • When an estimated debit becomes final.
  • How failed, canceled, refunded, or disputed usage is reversed.
  • How the platform's margin and the model provider's cost are reported.

Decide who is the merchant before writing code

“Stripe for AI” can describe several legal and technical arrangements. Choose one explicitly before designing the API.

ModelWho sells to the user?What your platform operates
App-owned checkoutThe AI appWallet, ledger, metering, tax inputs, support
Connected-account platformA connected merchantOnboarding, routing, fees, payouts, platform ledger
Merchant of recordThe MoR providerProduct entitlements and usage synchronization

A payment processor is not automatically a merchant of record. Tax collection, invoicing, refunds, chargebacks, sanctions screening, and consumer-law duties depend on the contract and jurisdiction. Have qualified legal and accounting teams review the model; an SDK abstraction does not transfer those obligations.

The minimum architecture

An embeddable payments system for an AI app needs six durable parts:

  1. Customer mapping: links the application's user or organization to a payment-provider customer and one or more wallets.
  2. Checkout or top-up session: lets the user buy a defined credit package through hosted payment elements.
  3. Immutable ledger: records credits, debits, holds, releases, refunds, adjustments, and disputes as append-only entries.
  4. Usage authorization: checks balance and policy before an AI request runs.
  5. Settlement: replaces an estimated hold with the actual charge after the model call completes.
  6. Reconciliation: compares provider payments, wallet entries, AI usage, and payouts so missing or duplicated records are visible.

Do not store a mutable number as the only record of balance. A cached balance is useful for fast reads, but it should be derived from ledger entries or updated in the same atomic transaction. Otherwise, there is no reliable explanation for a customer dispute.

Model the wallet as an append-only ledger

A practical ledger entry might look like this:

type LedgerEntry = {
  id: string;
  walletId: string;
  type: "top_up" | "hold" | "debit" | "release" | "refund" | "adjustment";
  amountMicros: bigint;
  currency: "USD";
  idempotencyKey: string;
  paymentId?: string;
  requestId?: string;
  reversesEntryId?: string;
  createdAt: string;
};

Use integer minor units or a fixed-precision decimal type. Never use binary floating-point arithmetic for money. If the product exposes “credits,” define a versioned conversion between credits and currency so a pricing change does not rewrite historical transactions.

Every correction should create a new reversing entry. Do not edit or delete the original debit. An immutable history makes accounting, support, and incident response far simpler.

Use short-lived browser sessions

The frontend needs enough authority to render a wallet balance, start a checkout, and request approved AI features. It must never receive the platform's payment secret or an unrestricted server API key.

The host application's server should mint a short-lived session:

type CreateBillingSession = {
  externalCustomerId: string;
  allowedOrigins: string[];
  walletId: string;
  allowedFeatures: string[];
  maxSpendMicros: bigint;
  expiresInSeconds: number;
};

const session = await billing.sessions.create({
  externalCustomerId: user.id,
  allowedOrigins: ["https://app.example.com"],
  walletId: user.walletId,
  allowedFeatures: ["chat", "image-generation"],
  maxSpendMicros: 2_000_000n,
  expiresInSeconds: 900,
});

Sign the session with a server-held key and validate its audience, issuer, expiration, origin, wallet, customer, and scope on every SDK request. Keep the lifetime short and support revocation for compromised sessions.

Origin checks are useful but insufficient by themselves. A malicious script on an allowed origin may still act as the user. Use normal application authentication, Content Security Policy, dependency controls, and authorization on every operation.

Build checkout with provider-hosted elements

The React layer should orchestrate the experience without touching raw card data. A generic component contract could be:

<CreditWallet sessionToken={session.token}>
  <WalletBalance />
  <TopUpButton packageId="credits-25" />
  <PaymentElement />
  <TransactionHistory limit={20} />
</CreditWallet>

PaymentElement should come from the payment provider or render inside its hosted frame. This reduces the card-data surface, but it does not eliminate all PCI, privacy, or security responsibilities. Confirm the exact integration type with the provider's current compliance documentation.

Treat checkout completion in the browser as a user-interface event, not proof that money settled. Credit the wallet only after a verified server-to-server event or an authoritative payment-status lookup.

Make payment webhooks idempotent

Payment providers retry webhooks. Events can arrive late, more than once, and occasionally out of order. A correct handler should:

  1. Read the raw request body.
  2. Verify the provider signature and timestamp.
  3. Reject stale or invalid signatures.
  4. Insert the provider event ID into a unique processed-events table.
  5. Atomically create the corresponding ledger entry.
  6. Acknowledge only after the durable transaction succeeds.

The provider event ID prevents duplicate top-ups. A separate business idempotency key—such as payment:{paymentId}:credit—protects against the same payment being represented by more than one event type.

Do not call arbitrary callback URLs supplied by customers from the webhook handler. If outbound callbacks are supported, require HTTPS, validate destinations, block private and link-local networks, sign payloads, use short timeouts, and deliver them from a queue with bounded retries.

Reserve, run, and settle AI usage

AI costs are often unknown until the response completes. The wallet therefore needs a hold-and-settle flow rather than a single blind debit.

1. Estimate maximum allowed charge
2. Atomically place a hold
3. Start the AI request with one request ID
4. Capture actual model usage and application markup
5. Convert the hold into a final debit
6. Release any unused amount
7. Release the full hold if the request fails before billable work

The authorization transaction must prevent two simultaneous requests from both spending the same balance. Use a serializable transaction, row lock, compare-and-swap version, or another database mechanism that provides the required invariant.

If the AI provider charges for a failed request, decide whether the platform or the customer absorbs it. Make that rule explicit in product terms and encode it consistently. Silent differences between invoices and wallet history create support problems and can erase margin.

Calculate cost and markup separately

Keep at least three values for every settled request:

provider cost = input cost + output cost + cache cost + tool cost
platform fee  = fixed fee + percentage markup
customer debit = provider cost + platform fee - discount

Store the pricing version used for each component. Model providers change prices, and an AI app may update its markup independently. Historical debits must remain reproducible after either table changes.

Also define rounding once. For example, calculate in millionths of a dollar, round only when posting a ledger entry, and disclose any minimum request charge. Rounding each token component separately can produce a different result from rounding the final total.

Handle refunds, disputes, and negative balances

Top-up money is not always final. A refund or chargeback may arrive after credits have been spent. Pick and document a policy:

  • Freeze future usage until the deficit is repaid.
  • Allow a limited negative balance for trusted accounts.
  • Absorb the loss below a threshold.
  • Recover funds through an authorized payment method where legally permitted.

Never erase the original top-up. Add a reversal linked to the payment, then show the resulting balance and status in customer support tools.

Partial refunds require a defined relationship between cash and remaining credits. Promotional credits may be non-refundable while purchased credits are refundable, which means the ledger must distinguish them and define spend order.

Security checklist for an embeddable payments SDK

  • Keep payment and signing secrets on the server.
  • Use short-lived, scoped, audience-bound frontend sessions.
  • Restrict sessions by wallet, customer, origin, feature, and spending limit.
  • Verify webhook signatures against the raw body and enforce replay windows.
  • Require idempotency keys on checkout, top-up, authorization, and settlement.
  • Use integer or fixed-precision money values.
  • Make ledger writes atomic and immutable.
  • Rate-limit top-ups, balance checks, and expensive AI operations.
  • Prevent users from selecting unapproved model IDs or arbitrary provider URLs.
  • Redact secrets and payment data from application and model logs.
  • Audit manual adjustments and require elevated authorization.
  • Test insufficient funds, concurrency, timeouts, duplicate events, and refunds.

Test the failure paths, not just successful checkout

A sandbox test suite should include:

ScenarioExpected result
Duplicate successful-payment webhookWallet credited once
Webhook arrives before browser returnCredit appears when the client refreshes
Browser says success, webhook failsNo credit until authoritative verification succeeds
Two requests spend final balanceAt most one authorization succeeds
Model request times out before billingHold released
Provider bills a failed generationConfigured customer/platform policy applied
Partial settlementFinal debit plus release equals original hold
Refunded top-up already spentReversal and negative-balance policy applied
Pricing changes during an active runSettlement uses the recorded authorization version
Webhook replay has a valid signatureProcessed-event uniqueness prevents a second mutation

Add reconciliation tests that total all provider payments and compare them with top-up ledger entries, then total AI-provider usage and compare it with request cost records. A green checkout test cannot detect money that disappears between those systems.

Observe AI usage behind billing with Currai

An embeddable payments SDK answers who paid and how the wallet changed. Currai answers what the AI application did with that usage. Attach the billing customer, wallet, request, and pricing-version identifiers as trace metadata; record every model generation, tool call, token count, latency, error, and provider cost; then reconcile the final debit with the complete AI request.

Currai does not process payments, hold wallet balances, act as merchant of record, or replace Stripe, Paddle, or another payment provider. It is the observability and evaluation layer beside the billing system.

Start with token cost tracking, LLM cost budgets and alerts, and sessions and user grouping. Then create a free Currai account to connect customer charges to the AI requests that produced them.

03

Keep going with nearby topics from the Currai blog.