> ## Documentation Index
> Fetch the complete documentation index at: https://tonic-ai.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# RevenueCat Setup for the Server

> Configure RevenueCat on your account and connect the CreditNexus server for entitlements and subscription upgrades

This guide explains how to set up **RevenueCat** on your account and configure the **CreditNexus server** so it can check entitlements and grant Pro (or custom) access after payments (x402 or in-app).

***

## 1. Overview

| Component                 | Role                                                                                                                                                                                               |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **RevenueCat Dashboard**  | Create project, connect stores (Apple, Google, Stripe, etc.), add products, create entitlement(s), create offering(s), optional paywall.                                                           |
| **RevenueCat Server API** | CreditNexus server uses the **Secret API key** (sk\_...) to: (1) check subscriber entitlements (`GET /v1/subscribers/{app_user_id}`), (2) grant promotional entitlements (`POST .../promotional`). |
| **CreditNexus server**    | Uses `REVENUECAT_ENABLED`, `REVENUECAT_API_KEY`, `REVENUECAT_ENTITLEMENT_PRO`; identifies users as `app_user_id = str(user.id)` (CreditNexus user ID).                                             |

**Code**: `app/services/revenuecat_service.py`, `app/api/subscription_routes.py`, `app/services/payment_router_service.py`

***

## 2. RevenueCat Dashboard Setup

### 2.1 Create or select a project

1. Go to [RevenueCat](https://app.revenuecat.com).
2. Create a **new project** or select an existing one. Projects are top-level containers for apps, products, entitlements, and paywalls.

### 2.2 Connect to a store

Depending on your platforms, connect at least one store:

* **Apple App Store**: [iOS Product Setup](https://www.revenuecat.com/docs/offerings/products/setup-index#-ios-product-setup) — App Store Connect, in-app purchases.
* **Google Play**: [Google Play Product Setup](https://www.revenuecat.com/docs/offerings/products/setup-index#-google-play-product-setup) — Google Play Console, subscriptions/products.
* **Stripe**: [Stripe Product Setup](https://www.revenuecat.com/docs/offerings/products/setup-index) — for web or custom billing.
* **Paddle**: [Paddle Product Setup](https://www.revenuecat.com/docs/offerings/products/setup-index#-paddle-product-setup) — for web.

Add the **products** you plan to sell (e.g. monthly subscription, org-admin one-time, etc.) in each store.

### 2.3 Create an entitlement

An **entitlement** represents a level of access (e.g. “Pro”) that you grant when a customer purchases a product.

1. In the RevenueCat dashboard, go to **Product catalog** → **Entitlements**.
2. **Create** an entitlement. The **identifier** is what the server uses in the REST API (e.g. **`entlfa0ee126b6`** — use the exact value shown in the dashboard).
3. Set **`REVENUECAT_ENTITLEMENT_PRO`** in `.env` to this exact identifier (e.g. `entlfa0ee126b6`).
4. **Attach** your products (from the linked store) to this entitlement.

The server calls `GET /v1/subscribers/{app_user_id}` and `POST .../entitlements/{entitlement_identifier}/promotional` using this identifier.

### 2.4 Products to add: subscribe + buy credits

The server expects these **product\_id** values when the client calls `POST /api/subscriptions/revenuecat/purchase`. Create products in your linked store (sandbox and/or production) and map them as below.

**Subscribe (entitlement + credits)**

| product\_id (client sends) | Use case                            | Server behavior                                                                         |
| -------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------- |
| `subscription_upgrade`     | Monthly Pro subscription            | Grant Pro entitlement P1M + `SUBSCRIPTION_UPGRADE_CREDITS` (default 200 pennies)        |
| `org_admin`                | Organization admin signup (\$2)     | Grant Pro (or org-admin) P1Y + mark org paid + `ORG_ADMIN_SIGNUP_CREDITS` (default 200) |
| `mobile_app`               | Mobile one-time purchase (\~\$3.60) | Grant Pro P1Y + `MOBILE_APP_PURCHASE_CREDITS` (default 360)                             |

* In RevenueCat **Products**: create or import from your store (e.g. Stripe, Paddle, App Store) products that map to these. The **store** product identifier can be anything; the **client** must send the `product_id` above when calling the CreditNexus server after purchase.
* **Attach** these three products to your **Pro entitlement** (e.g. `entlfa0ee126b6`).

**Buy credits (credits only, no entitlement)**

| product\_id (client sends) | Use case                           | Server behavior                                   |
| -------------------------- | ---------------------------------- | ------------------------------------------------- |
| `credit_top_up_100`        | \$1 worth of credits (100 pennies) | Add 100 credits (universal); no entitlement grant |
| `credit_top_up_500`        | \$5 worth (500 pennies)            | Add 500 credits                                   |
| `credit_top_up_1000`       | \$10 worth (1000 pennies)          | Add 1000 credits                                  |
| `credit_top_up_<N>`        | Any N pennies                      | Add N credits                                     |

* Create **consumable or one-time** products in your store (e.g. “100 credits”, “500 credits”, “1000 credits”) and map them to `credit_top_up_100`, `credit_top_up_500`, `credit_top_up_1000`. The client sends that `product_id` after purchase; the server adds that many credits (pennies).
* **Do not** attach credit-pack products to the Pro entitlement; the server only adds credits and does not grant entitlement for these.

**Summary: RevenueCat store setup**

1. **Entitlements**: One entitlement, e.g. identifier `entlfa0ee126b6` (Pro).
2. **Products (store)**: Create in your linked store:
   * **Subscribe**: e.g. “Pro Monthly”, “Org Admin (\$2)”, “Mobile Unlock” → map to `subscription_upgrade`, `org_admin`, `mobile_app`. Attach all three to the Pro entitlement.
   * **Buy credits**: e.g. “100 credits”, “500 credits”, “1000 credits” → map to `credit_top_up_100`, `credit_top_up_500`, `credit_top_up_1000`. Do not attach to entitlement.
3. **Offerings**: Create at least one offering (e.g. **default**) and add **packages**:
   * Packages for subscribe: subscription\_upgrade, org\_admin, mobile\_app.
   * Packages for buy credits: credit\_top\_up\_100, credit\_top\_up\_500, credit\_top\_up\_1000 (or more packs as you like).
   * You can use one offering with all packages, or two offerings (e.g. “default” = subscription, “credits” = credit packs). Set one as **current** for the paywall.
4. **Paywall**: Use RevenueCat Paywalls (or your own UI) to show “Subscribe” and “Buy credits” options. After any purchase, the client calls `POST /api/subscriptions/revenuecat/purchase` with the corresponding `product_id`.

### 2.5 Create an offering

An **offering** is a set of products you show on a paywall. Create at least one offering (e.g. **default**) and add **packages** that reference your products. The server does not require a specific offering ID; the SDK uses offerings to display the paywall. Set the offering as **current** if you use a single default.

### 2.6 Configure a paywall (optional)

Use RevenueCat **Paywalls** to build the purchase UI remotely. The CreditNexus web app can still use x402 for web payments; the paywall is most useful for native (iOS/Android) or when you use RevenueCat’s paywall UI.

***

## 3. Get the Secret API key (for the server)

The server must use a **Secret API key** (sk\_...) — never a public key — for REST API calls.

1. In the RevenueCat dashboard, open your **project**.
2. Go to **Project settings** → **API keys** (or **Authentication**).
3. Create or copy a **Secret API key** (starts with `sk_`).
   * Never expose this key in the client or in version control.
   * Use it only in server-side environment variables.

Documentation: [RevenueCat API Keys & Authentication](https://www.revenuecat.com/docs/projects/authentication).

***

## 4. Server configuration (.env)

In the **project root** `.env`:

```env theme={null}
# RevenueCat
REVENUECAT_ENABLED=true
REVENUECAT_API_KEY=sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
REVENUECAT_ENTITLEMENT_PRO=entlfa0ee126b6
```

| Variable                     | Description                                                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `REVENUECAT_ENABLED`         | Set to `true` to enable entitlement checks and promotional grants.                                                |
| `REVENUECAT_API_KEY`         | **Secret** API key (sk\_...). Required when `REVENUECAT_ENABLED=true`.                                            |
| `REVENUECAT_ENTITLEMENT_PRO` | Entitlement identifier (e.g. `entlfa0ee126b6`). Must match the identifier in RevenueCat Dashboard → Entitlements. |

Optional:

* `REVENUECAT_ENTITLEMENT_ORG_ADMIN` — if you use a separate entitlement for org-admin; otherwise server falls back to `REVENUECAT_ENTITLEMENT_PRO`.
* `REVENUECAT_ENTITLEMENT_MARKET_INTELLIGENCE` — for surveillance/premium features; otherwise falls back to `REVENUECAT_ENTITLEMENT_PRO`.

**Code reference**: `app/core/config.py`

***

## 5. How the server uses RevenueCat

### 5.1 User identification

The server identifies users to RevenueCat with **`app_user_id = str(user.id)`** (CreditNexus user ID). When you use the RevenueCat SDK on a client (e.g. mobile), you should **identify** the user with the same ID after login:

```text theme={null}
Purchases.logIn(str(creditnexus_user_id))
```

So RevenueCat’s subscriber and the server’s user are the same entity.

### 5.2 Entitlement check

* **Endpoint**: `GET /api/subscriptions/entitlement`
* **Server**: Calls RevenueCat REST API `GET /v1/subscribers/{app_user_id}` and checks the entitlement (e.g. `pro`) in the response. Returns e.g. `{ "has_pro": true }` or `{ "has_pro": false }`.

### 5.3 After x402 payment (subscription upgrade / org-admin)

When a user completes an x402 payment (e.g. subscription upgrade or org-admin signup), the server can **grant** a RevenueCat promotional entitlement so they get Pro (or org-admin) access in RevenueCat as well:

* **Server**: Calls RevenueCat REST API `POST /v1/subscribers/{app_user_id}/entitlements/{entitlement_id}/promotional` with duration (e.g. P1M, P1Y).
* **Code**: `PaymentRouterService.after_subscription_payment()` → `RevenueCatService.grant_promotional_entitlement()`.

### 5.4 In-app purchase (mobile) → server

When the user pays **in-app** (RevenueCat SDK), the client should call the CreditNexus server so the server can grant access and allocate credits:

* **Endpoint**: `POST /api/subscriptions/revenuecat/purchase`
* **Body**: `{ "product_id": "subscription_upgrade" | "org_admin" | "mobile_app" | "credit_top_up_500", "transaction_id": "...", "purchase_token": "..." }` (transaction\_id and purchase\_token optional).

The server uses **product\_id** to either grant entitlement + credits (subscribe) or only add credits (buy credits). The server does **not** re-verify the receipt with RevenueCat in the current implementation; it trusts the client to have completed the purchase via the SDK. For stricter security you could add server-side receipt validation.

***

## 6. Product IDs the server expects

When calling `POST /api/subscriptions/revenuecat/purchase`, the server handles **product\_id** as follows:

**Subscribe (entitlement + credits)**

| product\_id            | Entitlement                                                        | Duration      | Use case                                                                      |
| ---------------------- | ------------------------------------------------------------------ | ------------- | ----------------------------------------------------------------------------- |
| `subscription_upgrade` | `REVENUECAT_ENTITLEMENT_PRO`                                       | P1M (1 month) | Monthly subscription upgrade.                                                 |
| `org_admin`            | `REVENUECAT_ENTITLEMENT_ORG_ADMIN` or `REVENUECAT_ENTITLEMENT_PRO` | P1Y (1 year)  | Org-admin signup payment.                                                     |
| `mobile_app`           | `REVENUECAT_ENTITLEMENT_PRO`                                       | P1Y           | Mobile app one-time purchase; server allocates `MOBILE_APP_PURCHASE_CREDITS`. |

**Buy credits (credits only, no entitlement)**

| product\_id                                                                               | Server behavior                                            |
| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `credit_top_up_<N>` (e.g. `credit_top_up_100`, `credit_top_up_500`, `credit_top_up_1000`) | Add N credits (pennies) to the user; no entitlement grant. |

Create **products** in RevenueCat (and in each store) that map to these **product\_id** values (or align your client to send these when calling the server).

***

## 7. Payment flow summary

| Flow                              | Client                                                                                    | Server                                                                                                                                                      |
| --------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Web (x402)**                    | User pays via x402; server receives payment and optionally grants RevenueCat entitlement. | `POST /api/subscriptions/upgrade` or `POST /api/subscriptions/org-admin/upgrade`; after settle, `after_subscription_payment()` grants entitlement.          |
| **Mobile / Web (RevenueCat SDK)** | User subscribes or buys credits in-app; client calls CreditNexus server with product\_id. | `POST /api/subscriptions/revenuecat/purchase` with product\_id; server grants entitlement + credits (subscribe) or only adds credits (credit\_top\_up\_\*). |

When RevenueCat is enabled, 402 responses from the server can include `revenuecat_available: true` and `revenuecat_endpoint: "/api/subscriptions/revenuecat/purchase"` so the client knows it can offer an in-app purchase path.

***

## 8. Alignment: RevenueCat, Plaid, and MetaMask

All paywalled flows use the same pattern: **credits first**, then **402 payment required** if insufficient. Payment can be completed via **MetaMask** (x402), **facilitator**, or **RevenueCat** (in-app / card).

| Flow                                                            | Credits / entitlement                                                                                           | If insufficient                                                              | Payment options                                                                                                                                                                                                 |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Billable feature** (predictions, agents, green finance, etc.) | `require_credits_or_402` spends rolling credits (pennies).                                                      | 402 with `payment_request`; `revenuecat_available` when RevenueCat enabled.  | MetaMask (x402), facilitator, or RevenueCat (client calls `POST /api/subscriptions/revenuecat/purchase` with product\_id for subscription/org\_admin; credit top-up uses `POST /api/credits/top-up` with x402). |
| **Credit top-up**                                               | User must have org unlocked (subscription or credits).                                                          | 402 with payment\_request.                                                   | MetaMask (x402), facilitator. Amount in USD; server adds **credits = pennies** (1 USD = 100 by default, `CREDITS_PENNIES_PER_USD`).                                                                             |
| **Subscription upgrade / org-admin**                            | N/A (user is paying to get access).                                                                             | 402 with payment\_request; `revenuecat_available` and `revenuecat_endpoint`. | MetaMask (x402), facilitator, or RevenueCat (client sends product\_id `subscription_upgrade` or `org_admin` after in-app purchase).                                                                             |
| **Plaid (banking)**                                             | Banking routes use `require_credits_or_402` with `BILLABLE_FEATURE`; 1 credit per call (or cost in USD in 402). | 402; user pays via MetaMask/RevenueCat or tops up credits.                   | Same as billable feature. Plaid does not "pay" directly — user consumes credits or completes 402.                                                                                                               |

**Business model: subscribe or pay-as-you-go**

* **Subscribe**: User pays once (e.g. $2 web, ~$3.60 mobile); server grants entitlement and credits (`ORG_ADMIN_SIGNUP_CREDITS`, `SUBSCRIPTION_UPGRADE_CREDITS`, `MOBILE_APP_PURCHASE_CREDITS`). Credits ≈ dollar value (e.g. 200 pennies = $2, 360 = $3.60).
* **Pay-as-you-go**: User tops up credits via `POST /api/credits/top-up` (MetaMask/facilitator or RevenueCat). Services (dashboard refresh = Plaid accounts/balances/transactions, predictions, agents, green finance, brokerage fund/withdraw) cost credits; if insufficient, 402 with payment options (MetaMask, RevenueCat).
* **Plaid markup**: `PLAID_COST_USD` is the base cost per API call; `PLAID_MARKUP_PERCENT` adds a percentage (e.g. 20 = 20% markup). Final charge in 402 = `PLAID_COST_USD * (1 + PLAID_MARKUP_PERCENT/100)`.
* **Brokerage transfers**: Optional `BROKERAGE_TRANSFER_FEE_CREDITS` (0 = no fee). When > 0, each fund/withdraw deducts that many credits (subscribe or pay-as-you-go).

**What to configure:**

1. **RevenueCat**: One entitlement (e.g. `entlfa0ee126b6`), three products attached (`subscription_upgrade`, `org_admin`, `mobile_app`), one offering with packages. Set `REVENUECAT_ENTITLEMENT_PRO=entlfa0ee126b6` in `.env`.
2. **Credits = pennies**: Set `CREDITS_PENNIES_PER_USD=100` (default) so 1 USD top-up adds 100 credits (pennies). Set `ORG_ADMIN_SIGNUP_CREDITS`, `SUBSCRIPTION_UPGRADE_CREDITS`, `MOBILE_APP_PURCHASE_CREDITS` for credits granted per purchase (defaults 200, 200, 360).
3. **Billable cost**: `BILLABLE_FEATURE_COST_USD` (default 0.10) is the USD amount shown in 402 for predictions, agents, green finance when credits are insufficient.
4. **x402 / MetaMask**: Configure `X402_ENABLED`, `X402_FACILITATOR_URL`, `X402_NETWORK`, `X402_TOKEN` for web/MetaMask payments.
5. **Plaid**: Configure `PLAID_*` for linking; `PLAID_COST_USD` is the base cost per call; `PLAID_MARKUP_PERCENT` adds markup. Banking (dashboard refresh) uses the same credit/402 flow.
6. **Brokerage**: `BROKERAGE_TRANSFER_FEE_CREDITS` (default 0) = credits per fund/withdraw; 0 = no fee.

***

## 9. Troubleshooting

| Symptom                       | Check                                                                                                                                                                                                                                                             |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Entitlement always false      | `REVENUECAT_ENABLED=true`, `REVENUECAT_API_KEY=sk_...` set in project root `.env`. Entitlement identifier in dashboard (e.g. `entlfa0ee126b6`) matches `REVENUECAT_ENTITLEMENT_PRO`. User identified in RevenueCat with same `app_user_id` (CreditNexus user ID). |
| 503 RevenueCat not enabled    | Set `REVENUECAT_ENABLED=true` and restart the server.                                                                                                                                                                                                             |
| Grant entitlement fails       | Verify Secret API key has permission to grant entitlements. Check dashboard **API keys** and that the key is **Secret** (sk\_). Check server logs for RevenueCat API error message.                                                                               |
| Mobile purchase not reflected | Ensure client calls `POST /api/subscriptions/revenuecat/purchase` with the correct `product_id` after purchase, and that the user is logged in (so `current_user.id` matches the RevenueCat app\_user\_id).                                                       |

***

## 10. References

* **RevenueCat**: [Getting Started](https://www.revenuecat.com/docs/getting-started/installation/expo), [Projects & Authentication](https://www.revenuecat.com/docs/projects/authentication), [Products Setup](https://www.revenuecat.com/docs/offerings/products/setup-index)
* **CreditNexus configuration**: [Configuration — RevenueCat](/getting-started/configuration#revenuecat-configuration)
* **Payment systems**: [Payment Systems](/features/payment-systems)
