# How the AutoGPT Platform Credit Billing System Works: Architecture & Implementation

> Explore the AutoGPT Platform credit billing system. Learn how it uses atomic PostgreSQL transactions & Stripe integration for seamless credit management, top-ups, refunds, and billing portal features.

- Repository: [AutoGPT/AutoGPT](https://github.com/Significant-Gravitas/AutoGPT)
- Tags: architecture
- Published: 2026-02-24

---

**The AutoGPT Platform credit billing system treats credits as internal currency managed through atomic PostgreSQL transactions and Stripe integration, enabling manual top-ups, automatic refills, refunds, and billing portal management.**

The AutoGPT Platform (Significant-Gravitas/AutoGPT) implements a sophisticated credit billing system that handles agent execution costs as an internal currency. This architecture combines PostgreSQL's atomic transaction capabilities with Stripe's payment infrastructure to ensure secure, race-condition-free credit management at scale. Understanding this implementation reveals how the platform balances complex financial operations with high-concurrency agent execution.

## Core Architecture and Data Model

The credit system centers on two primary database tables and a modular Python class structure that separates ledger logic from payment processing.

### Database Schema: Immutable Ledger and Balance Cache

All credit operations rely on two PostgreSQL tables defined in the backend data layer:

- **`CreditTransaction`**: An immutable ledger logging every credit change, including top-ups, usage deductions, grants, and refunds
- **`UserBalance`**: A cached current balance for fast reads, synchronized atomically with the transaction log via Common Table Expressions (CTEs)

### The UserCredit Model

Located in [`autogpt_platform/backend/backend/data/credit.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/autogpt_platform/backend/backend/data/credit.py), the `UserCredit` class (and its fallback `BetaUserCredit`) implements all credit logic, including spending, top-ups, refunds, auto-refill triggers, and Stripe billing portal integration. The `get_user_credit_model` function (lines 96-120) selects between production `UserCredit` and beta modes based on the LaunchDarkly feature flag `ENABLE_PLATFORM_PAYMENT`.

## Atomic Transaction Processing

The system guarantees financial consistency through database-level locking mechanisms that prevent race conditions during concurrent operations.

### The _add_transaction Method

The `_add_transaction` method (lines 359-426 in [`credit.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/credit.py)) serves as the single point of entry for all credit mutations. It executes a Common Table Expression (CTE) with `FOR UPDATE` locking on the `UserBalance` row, preventing race conditions during concurrent agent executions. This method handles ceiling protection, underflow prevention, and simultaneous updates to both the `CreditTransaction` log and `UserBalance` cache in one atomic database call.

### Spending Credits During Agent Execution

When agent blocks execute, the `spend_credits` method creates negative transactions via `_add_transaction`, passing the execution cost as a negative amount with `transaction_type=CreditTransactionType.USAGE`. If the resulting balance falls below the user's configured auto-top-up threshold, the system automatically triggers `request_auto_top_up` (lines 158-165) to prevent service interruption.

```python

# Inside spend_credits (UserCredit)

balance, _ = await self._add_transaction(
    user_id=user_id,
    amount=-cost,                     # negative → spend

    transaction_type=CreditTransactionType.USAGE,
    metadata=SafeJson(metadata.model_dump()),
)

```

## Stripe Integration and Payment Flows

The platform leverages Stripe for payment processing while maintaining internal credit accounting to decouple usage metering from payment provider logic.

### Manual Top-Up Workflow

The `_top_up_credits` method (lines 736-805) creates Stripe `PaymentIntent` or `SetupIntent` objects, storing pending transactions as inactive records in the database. The frontend initiates this through `requestTopUp`, which calls the backend checkout flow. Upon Stripe confirmation, `fulfillCheckout` activates the transaction via `_enable_transaction`, atomically updating the `UserBalance` and enabling the credits for immediate use.

### Billing Portal Access

The `create_billing_portal_session` method (lines 226-233) generates Stripe Billing Portal URLs using `stripe.billing_portal.Session.create`. Users access this functionality through the `/profile/credits` page located at `autogpt_platform/frontend/src/app/(platform)/profile/(user)/credits/page.tsx`, which calls `api.getUserPaymentPortalLink()` to hit the `GET /credits/manage` endpoint defined in [`autogpt_platform/backend/backend/api/features/v1.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/autogpt_platform/backend/backend/api/features/v1.py) (lines 51-62).

### Auto-Top-Up Configuration

Users configure automatic refills through the `User.top_up_config` JSON field. When `spend_credits` detects a balance below the configured threshold, it invokes `top_up_credits` automatically without user intervention. The frontend submits these configurations via `updateAutoTopUpConfig`, which updates the backend through the `set_auto_top_up` endpoint.

```typescript
// Auto-refill form submit
const submitAutoTopUpConfig = (e) => {
  e.preventDefault();
  const form = e.currentTarget;
  const amount = Number(form.topUpAmount.value) * 100;
  const threshold = Number(form.threshold.value) * 100;
  updateAutoTopUpConfig(amount, threshold)
    .then(() => toast({ title: 'Auto top-up config updated!' }))
    .catch(toastOnFail('update auto top-up config'));
};

```

## Refund and Dispute Management

The system handles financial reversals through structured workflows that maintain ledger integrity while complying with payment provider requirements.

### Processing Refunds

The `top_up_refund` method (lines 610-654) creates `CreditRefundRequest` records. If the user's remaining balance covers the top-up amount, Stripe processes an automatic refund via `stripe.Refund.create`; otherwise, the system registers a manual request for administrator review. The frontend triggers this through `refundTopUp` in the refund modal interface.

```typescript
// In RefundModal.tsx
const refundCredits = (txKey, reason) =>
  refundTopUp(txKey, reason)
    .then(amount => {
      if (amount > 0) { /* auto-approved */ }
      else { /* manual review */ }
    })
    .catch(toastOnFail('refund transaction'));

```

### Handling Disputes

Stripe webhook events (`charge.dispute.created`, `charge.dispute.closed`) invoke `handle_dispute` and `deduct_credits` (lines 676-743). These methods adjust `UserBalance` records and trigger notification emails through the notification system to alert administrators and users of account adjustments.

## Frontend Implementation

The credit management UI resides in `autogpt_platform/frontend/src/app/(platform)/profile/(user)/credits/page.tsx`, utilizing a custom `useCredits` hook to interact with the REST API endpoints defined in [`autogpt_platform/backend/backend/api/features/v1.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/autogpt_platform/backend/backend/api/features/v1.py).

Opening the billing portal:

```typescript
// Inside CreditsPage.tsx
const openBillingPortal = () =>
  api.getUserPaymentPortalLink()
    .then(portal => router.push(portal.url))
    .catch(toastOnFail('open billing portal'));

```

Initiating manual top-ups:

```typescript
// Submit handler in CreditsPage.tsx
const submitTopUp = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  const amount = parseInt(new FormData(e.currentTarget).get('topUpAmount') as string) * 100;
  requestTopUp(amount).catch(toastOnFail('request top-up'));
};

```

## Security and Feature Flags

The entire credit billing system is gated by the **LaunchDarkly** feature flag `ENABLE_PLATFORM_PAYMENT`. When disabled, the system falls back to `BetaUserCredit`, which provides fixed monthly refills without Stripe integration. All API routes enforce authentication through `Security(requires_user)`, validating JWT tokens and extracting `user_id` for every credit operation to ensure users can only modify their own balances.

## Summary

- The AutoGPT Platform credit billing system uses **atomic PostgreSQL transactions** with row-level locking (`FOR UPDATE`) to prevent race conditions during concurrent agent executions.
- **Stripe integration** handles payment intents, billing portals, and refunds while the platform maintains an internal `CreditTransaction` ledger in [`autogpt_platform/backend/backend/data/credit.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/autogpt_platform/backend/backend/data/credit.py).
- **Auto-top-up functionality** automatically refills credits when balances drop below user-defined thresholds stored in `User.top_up_config`.
- The system supports **full refund workflows** and **dispute handling** through Stripe webhooks (`refund.created`, `charge.dispute.*`) and manual review processes.
- **Feature flags** allow seamless switching between production billing (`UserCredit`) and beta credit models (`BetaUserCredit`).

## Frequently Asked Questions

### How does AutoGPT Platform prevent race conditions when multiple agents spend credits simultaneously?

The platform uses a PostgreSQL Common Table Expression (CTE) with `FOR UPDATE` locking in the `_add_transaction` method (lines 359-426 of [`autogpt_platform/backend/backend/data/credit.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/main/autogpt_platform/backend/backend/data/credit.py)). This locks the user's `UserBalance` row during the transaction, ensuring that concurrent credit deductions read the correct balance and preventing double-spending scenarios even under high concurrency.

### What happens when a user's credit balance drops below the auto-top-up threshold during agent execution?

The `spend_credits` method automatically triggers `request_auto_top_up` (lines 158-165) when a usage transaction causes the balance to fall below the threshold defined in `User.top_up_config`. The system then creates a Stripe `PaymentIntent` via `_top_up_credits` to refill the account, allowing agent execution to continue uninterrupted once the payment processes.

### How does the refund process work in the AutoGPT Platform credit system?

The `top_up_refund` method creates a `CreditRefundRequest` record and checks if the user's current balance covers the refund amount. If sufficient funds exist, it processes an immediate Stripe refund via `stripe.Refund.create` and deducts the credits atomically. If not, it registers a manual refund request for administrator review, ensuring the ledger remains balanced while complying with financial regulations.

### Can users manage their payment methods without leaving the AutoGPT Platform interface?

Yes. The `create_billing_portal_session` method generates a Stripe Billing Portal session URL that users access through the `/profile/credits` page. While Stripe hosts the actual payment management interface, the seamless redirect and return URL configuration create an integrated experience. The frontend calls `api.getUserPaymentPortalLink()` which hits the `GET /credits/manage` endpoint to retrieve the session URL.