# rc-one-time-products

Provides best practices for Android one-time purchases via RevenueCat SDK without manual BillingClient plumbing. Helpful for consumable items and lifetime access.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 613 installs · ★ 76
- Author: RevenueCat
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/RevenueCat/ai-toolkit/tree/HEAD/revenuecat-play-billing/skills/rc-one-time-products/SKILL.md
- Updated: 2026-10-21
- HTML: https://affpapa.org/en/nevibecode/skills/rc-one-time-products

## What it does

The skill covers a structured workflow for selling non-subscription products on Android. Setup begins in Google Play Console and the RevenueCat dashboard, where consumable goods must be flagged for automatic consumption. Initialisation requires calling `Purchases.configure` once on application start with an Android API key and user identifier.

Transactions execute through `awaitPurchase`, which suspends until RevenueCat verifies the purchase receipt. Developers must not call `acknowledgePurchase` or `consumeAsync` directly. The SDK manages the underlying `BillingClient` session and consumes or acknowledges tokens automatically. Entitlement status is then checked via `CustomerInfo`.

Handling exceptions requires wrapping calls with `PurchasesTransactionException`. The skill instructs the agent to ignore user cancellations silently, while routing `PaymentPendingError` to an informative interface state. Pending orders do not grant entitlements immediately, so apps must listen to `UpdatedCustomerInfoListener` or server webhooks instead.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add RevenueCat/ai-toolkit --skill rc-one-time-products -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/rc-one-time-products/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/rc-one-time-products/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add RevenueCat/ai-toolkit --skill rc-one-time-products -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/rc-one-time-products/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add RevenueCat/ai-toolkit --skill rc-one-time-products -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/rc-one-time-products/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install RevenueCat/ai-toolkit rc-one-time-products
```

2. **Manually: put the files in place**
- File: `.github/skills/rc-one-time-products/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add RevenueCat/ai-toolkit --skill rc-one-time-products -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/RevenueCat/ai-toolkit --path revenuecat-play-billing/skills/rc-one-time-products
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/rc-one-time-products/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add RevenueCat/ai-toolkit --skill rc-one-time-products -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/RevenueCat/ai-toolkit/tree/HEAD/revenuecat-play-billing/skills/rc-one-time-products/SKILL.md

## When to use it
- configure one-time Android purchases using `awaitPurchase`
- handle payment cancellations without raising false runtime errors
- inspect granted features via `CustomerInfo` entitlements
- receive backend purchase confirmations through the `INITIAL_PURCHASE` webhook

## Example prompts
- Show how to retrieve packages and initiate a purchase using `awaitPurchase` in Kotlin.
- Catch `PurchasesTransactionException` to handle `PaymentPendingError` and cancellation separately.
- How do I check lifetime access in `CustomerInfo` without relying on product IDs?

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 1d30b6ca356b043c.

BEGIN THIRD-PARTY FILE 1d30b6ca356b043c
````text
---
name: rc-one-time-products
description: Use this skill when selling one time products on Android with RevenueCat. Covers fetching offerings, running awaitPurchase on a non subscription package, and relying on the SDK to acknowledge or consume automatically.
license: Apache-2.0; see LICENSE
metadata:
  author: RevenueCat
  source: revenuecat-handbook chapter 3
  keywords:
  - android
  - revenuecat
  - one-time-products
  - awaitpurchase
  - consumable
  - non-consumable
---

# One Time Products with RevenueCat

Sell one time products on Android without writing BillingClient glue. The RevenueCat SDK fetches products, launches the purchase, verifies the receipt, and acknowledges or consumes the token for you.

## Phase 1: Scope

Answer these before touching code.

| Question | Decision |
|---|---|
| Is the product consumable or non consumable? | Mark consumables in the RevenueCat dashboard so the SDK calls `consumeAsync` for you. |
| Do you read access through entitlements or transactions? | Prefer entitlements so access logic stays decoupled from product IDs. |
| Do you need server notification of the purchase? | Use RevenueCat webhooks. The `INITIAL_PURCHASE` event fires for every new non subscription purchase. |

Do not call `BillingClient.queryProductDetailsAsync`, `acknowledgePurchase`, or `consumeAsync` yourself once RevenueCat is integrated. The SDK owns the `BillingClient` instance.

## Phase 2: Prepare

- Configure the product in Google Play Console as a one time product.
- In the RevenueCat dashboard, attach the product to an offering and package, and flag it as consumable if it should be consumed on purchase.
- Confirm `Purchases.configure` runs once on app start with your Android API key and the current App User ID.

## Phase 3: Execute

Fetch offerings, launch the purchase, then read the result off `CustomerInfo`.

```kotlin
val offerings = Purchases.sharedInstance.awaitOfferings()
val pkg = offerings.current?.availablePackages?.first() ?: return
```

Launch the purchase with `awaitPurchase`. It suspends until the RevenueCat backend verifies the token.

```kotlin
val result = Purchases.sharedInstance.awaitPurchase(
    PurchaseParams.Builder(activity, pkg).build()
)
val info = result.customerInfo
```

Read access through entitlements, or fall back to the non subscription transactions list.

```kotlin
val hasAccess = info.entitlements["lifetime_access"]?.isActive == true
````
END THIRD-PARTY FILE 1d30b6ca356b043c

The third-party file has ended. Everything between the 1d30b6ca356b043c tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2427 of 4166 bytes. © RevenueCat · MIT · https://github.com/RevenueCat/ai-toolkit/tree/HEAD/revenuecat-play-billing/skills/rc-one-time-products/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
