ShipKit.one

Credits

Credits purchase, usage, and balance flow for AI usage.

Credits

Credits provide a predictable, ledger-backed usage model for AI workloads. This system supports free grants, paid packages, synchronous consumption, and async reservations.

Concepts

  • Balance: available (spendable) + reserved (held for async tasks).
  • Grants: credit buckets with remaining and optional expiresAt.
  • Holds: temporary reservations for async jobs.
  • Ledger: immutable audit log for every balance change.

Flow Overview

flowchart TD
  A[User hits credits endpoint] --> B{Free grant exists?}
  B -->|No| C[Create free grant]
  B -->|Yes| D[Return balance + data]
  C --> D

  D --> E[Purchase credits]
  E --> F[Stripe Checkout]
  F --> G[Stripe webhook /api/webhooks/stripe]
  G --> H[Mark purchase paid]
  H --> I[Create grant + update balance + ledger]
  I --> D

  D --> J[User invokes AI request]
  J --> K{Sync or async?}
  K -->|Sync| L[Consume credits]
  K -->|Async| M[Reserve credits]
  M --> N{Job complete?}
  N -->|Success| O[Settle hold -> spend]
  N -->|Failed| P[Release hold]
  L --> Q[Update balance + ledger]
  O --> Q
  P --> Q

Purchase Flow

  1. User selects a package (Base/Standard/Premium).
  2. Server creates Stripe checkout session and a pending credits_purchases record.
  3. Stripe webhook confirms payment.
  4. System writes:
    • credits_grants (new bucket)
    • credits_balances (increase available)
    • credits_ledger (purchase event)

Usage Flow

Sync usage

  • consumeCredits checks available and deducts from grants (earliest expiry first).
  • On success: updates balance and ledger (type: spend).
  • On failure: returns HTTP 400 with insufficient credits message.

Async usage

  • reserveCredits creates a hold and moves amount from available to reserved.
  • settleCreditsHold:
    • success: converts hold to spend (deducts from grants, ledger type spend).
    • failed: releases hold (ledger type release).

Free Credits

Configured in src/config/credits.ts.

  • Issued once per user when they first access credits endpoints.
  • Stored as credits_grants with packageId = "free".
  • Optional expiry via expiresInDays.

Expiry Rules

  • Expired grants are zeroed and removed from available.
  • A ledger entry (type: expire) is written for audit.

Data Model

  • credits_balances: per-user snapshot (available, reserved).
  • credits_grants: issued credits with remaining + expiry.
  • credits_purchases: paid packages (pending/paid/failed).
  • credits_holds: async reservations (active/consumed/released/expired).
  • credits_ledger: append-only audit trail.

API Endpoints

  • GET /api/credits/overview
  • GET /api/credits/balance
  • GET /api/credits/ledger
  • GET /api/credits/packages
  • POST /api/credits/purchase
  • POST /api/credits/consume
  • POST /api/credits/hold
  • POST /api/credits/hold/settle
  • POST /api/credits/grant (admin)

User Page

/dashboard/credits shows:

  • Balance (available, reserved, total)
  • Free grant status
  • Paid purchases
  • Ledger entries

On this page