RevenueCat.NET
2.0.0
See the version list below for details.
dotnet add package RevenueCat.NET --version 2.0.0
NuGet\Install-Package RevenueCat.NET -Version 2.0.0
<PackageReference Include="RevenueCat.NET" Version="2.0.0" />
<PackageVersion Include="RevenueCat.NET" Version="2.0.0" />
<PackageReference Include="RevenueCat.NET" />
paket add RevenueCat.NET --version 2.0.0
#r "nuget: RevenueCat.NET, 2.0.0"
#:package RevenueCat.NET@2.0.0
#addin nuget:?package=RevenueCat.NET&version=2.0.0
#tool nuget:?package=RevenueCat.NET&version=2.0.0
, # RevenueCat.NET
A professional, production-ready .NET 8 client library for the RevenueCat REST API v2.
Features
- Complete API Coverage: Full implementation of RevenueCat REST API v2 with 100+ endpoints
- Modern .NET 8: Built with latest C# features (primary constructors, records, file-scoped namespaces)
- SOLID Principles: Clean architecture with dependency injection support
- Type-Safe: Strong typing with nullable reference types and comprehensive models
- Async/Await: Fully asynchronous API with cancellation token support
- Resilient: Built-in retry logic, rate limiting handling, and timeout management
- Performance: Connection pooling, HTTP compression, and efficient JSON serialization
- Extensible: Interface-based design for easy testing and mocking
- Well-Documented: Comprehensive XML documentation and usage examples
Installation
dotnet add package RevenueCat.NET
Quick Start
using RevenueCat.NET;
var client = new RevenueCatClient("your_v2_api_key");
var projects = await client.Projects.ListAsync();
var customers = await client.Customers.ListAsync("proj_abc123");
var customer = await client.Customers.GetAsync(
"proj_abc123",
"customer_id",
expand: new[] { "attributes" }
);
Configuration
var client = new RevenueCatClient("your_api_key", options =>
{
options.Timeout = TimeSpan.FromSeconds(60);
options.MaxRetryAttempts = 5;
options.RetryDelay = TimeSpan.FromSeconds(1);
options.EnableRetryOnRateLimit = true;
});
Usage Examples
Projects
var projects = await client.Projects.ListAsync(limit: 20);
Apps
var apps = await client.Apps.ListAsync("proj_abc123");
var app = await client.Apps.CreateAsync("proj_abc123", new CreateAppRequest(
Name: "My iOS App",
Type: AppType.AppStore,
AppStore: new AppStoreConfig(
BundleId: "com.example.app",
SharedSecret: "your_shared_secret"
)
));
Customers
var customer = await client.Customers.CreateAsync("proj_abc123", new CreateCustomerRequest(
Id: "user_12345",
Attributes: new[]
{
new CustomerAttribute("$email", "user@example.com"),
new CustomerAttribute("$displayName", "John Doe")
}
));
await client.Customers.TransferAsync("proj_abc123", "old_customer_id",
new TransferCustomerRequest("new_customer_id"));
Products
var products = await client.Products.ListAsync(
"proj_abc123",
appId: "app_xyz789",
expand: new[] { "items.app" }
);
var product = await client.Products.CreateAsync("proj_abc123", new CreateProductRequest(
StoreIdentifier: "com.example.premium.monthly",
AppId: "app_xyz789",
Type: ProductType.Subscription,
DisplayName: "Premium Monthly"
));
Entitlements
var entitlement = await client.Entitlements.CreateAsync("proj_abc123",
new CreateEntitlementRequest(
LookupKey: "premium",
DisplayName: "Premium Access"
));
await client.Entitlements.AttachProductsAsync("proj_abc123", "ent_abc123",
new AttachProductsRequest(new[] { "prod_123", "prod_456" }));
Offerings & Packages
var offering = await client.Offerings.CreateAsync("proj_abc123",
new CreateOfferingRequest(
LookupKey: "default",
DisplayName: "Default Offering",
IsDefault: true
));
var package = await client.Packages.CreateAsync("proj_abc123", "offering_id",
new CreatePackageRequest(
LookupKey: "monthly",
DisplayName: "Monthly Package",
ProductId: "prod_123",
Position: 1
));
Subscriptions
var subscriptions = await client.Subscriptions.ListAsync("proj_abc123", "customer_id");
await client.Subscriptions.CancelAsync("proj_abc123", "customer_id", "sub_id");
await client.Subscriptions.RefundAsync("proj_abc123", "customer_id", "sub_id");
Purchases
var purchases = await client.Purchases.ListAsync("proj_abc123", "customer_id");
await client.Purchases.RefundAsync("proj_abc123", "customer_id", "purchase_id");
Charts & Metrics
var metrics = await client.Charts.GetMetricsAsync(
"proj_abc123",
ChartMetricType.Revenue,
startDate: 1704067200000, // Unix timestamp
endDate: 1735689600000,
appId: "app_123"
);
Error Handling
try
{
var customer = await client.Customers.GetAsync("proj_abc123", "customer_id");
}
catch (NotFoundException ex)
{
Console.WriteLine($"Customer not found: {ex.Message}");
}
catch (RateLimitException ex)
{
Console.WriteLine($"Rate limited. Retry after: {ex.ErrorResponse?.BackoffMs}ms");
}
catch (RevenueCatException ex)
{
Console.WriteLine($"API error: {ex.Message}");
Console.WriteLine($"Error type: {ex.ErrorResponse?.Type}");
}
Dependency Injection
services.AddSingleton<IRevenueCatClient>(sp =>
new RevenueCatClient("your_api_key"));
API Coverage
Core Resources
- ✅ Projects - List and manage projects
- ✅ Apps - Full CRUD operations for all store types
- ✅ Customers - Complete customer lifecycle management
- ✅ Products - Product catalog management
- ✅ Entitlements - Entitlement configuration and product attachment
- ✅ Offerings - Offering management with metadata support
- ✅ Packages - Package configuration with eligibility criteria
- ✅ Paywalls - Paywall creation and management
Transactions & Billing
- ✅ Subscriptions - List, search, cancel, refund operations
- ✅ Purchases - One-time purchase management and refunds
- ✅ Invoices - Invoice retrieval and file access
- ✅ Virtual Currency - Balance management and transactions
Analytics & Search
- ✅ Charts & Metrics - Revenue, MRR, ARR, churn, and more
- ✅ Search - Search subscriptions and purchases by store identifiers
Advanced Features
- ✅ Customer Transfer - Transfer data between customers
- ✅ Customer Attributes - Manage custom attributes
- ✅ Customer Aliases - List customer aliases
- ✅ Active Entitlements - Query customer entitlements
- ✅ Authenticated Management URLs - Generate customer portal links
- ✅ Store Product Creation - Push products to App Store Connect
- ✅ Expandable Fields - Reduce API calls with field expansion
- ✅ Pagination - Efficient handling of large datasets
Supported Stores
- ✅ Apple App Store
- ✅ Apple Mac App Store
- ✅ Google Play Store
- ✅ Amazon Appstore
- ✅ Stripe
- ✅ RevenueCat Billing (Web)
- ✅ Roku
- ✅ Paddle
- ✅ Promotional
Examples
Comprehensive examples are available in the examples/ directory:
- BasicUsage - Quick start guide
- CustomerManagement - Customer CRUD, attributes, transfer
- SubscriptionManagement - Subscription lifecycle, cancel, refund
- ProductCatalog - Products, entitlements, offerings, packages
- ErrorHandling - Error handling patterns and retry logic
- VirtualCurrency - Virtual currency management
- Pagination - Efficient pagination techniques
See the examples README for detailed information.
Advanced Usage
Expandable Fields
Reduce API calls by expanding related resources:
var customer = await client.Customers.GetAsync(
projectId,
customerId,
expand: new[] { "attributes", "active_entitlements" }
);
// Access expanded data directly
foreach (var attr in customer.Attributes.Items)
{
Console.WriteLine($"{attr.Key}: {attr.Value}");
}
Pagination
Efficiently handle large datasets:
string? startingAfter = null;
do
{
var page = await client.Customers.ListAsync(
projectId,
limit: 100,
startingAfter: startingAfter
);
// Process page.Items
// Get cursor for next page
if (page.NextPage != null)
{
var uri = new Uri(page.NextPage);
var query = HttpUtility.ParseQueryString(uri.Query);
startingAfter = query["starting_after"];
}
else
{
startingAfter = null;
}
} while (startingAfter != null);
Search Operations
Search by store identifiers:
// Search subscriptions
var subscriptions = await client.Subscriptions.SearchSubscriptionsAsync(
projectId,
storeSubscriptionIdentifier: "GPA.1234-5678-9012-34567"
);
// Search purchases
var purchases = await client.Purchases.SearchPurchasesAsync(
projectId,
storePurchaseIdentifier: "1000000123456789"
);
Virtual Currency
Manage in-app currencies:
// Add currency
var balance = await client.Customers.CreateVirtualCurrencyTransactionAsync(
projectId,
customerId,
new CreateVirtualCurrencyTransactionRequest("GEMS", 100),
idempotencyKey: "unique-key"
);
// Deduct currency
await client.Customers.CreateVirtualCurrencyTransactionAsync(
projectId,
customerId,
new CreateVirtualCurrencyTransactionRequest("GEMS", -25),
idempotencyKey: "another-unique-key"
);
Customer Transfer
Transfer data between customers:
var transfer = await client.Customers.TransferAsync(
projectId,
sourceCustomerId,
new TransferCustomerRequest(
TargetCustomerId: targetCustomerId,
AppIds: new[] { "app_123" } // Optional: filter by apps
)
);
API Coverage Matrix
| Resource | List | Get | Create | Update | Delete | Actions |
|---|---|---|---|---|---|---|
| Projects | ✅ | - | - | - | - | - |
| Apps | ✅ | ✅ | ✅ | ✅ | ✅ | Get StoreKit Config, List API Keys |
| Customers | ✅ | ✅ | ✅ | - | ✅ | Transfer, List Aliases, Manage Attributes |
| Products | ✅ | ✅ | ✅ | - | ✅ | Create in Store |
| Entitlements | ✅ | ✅ | ✅ | ✅ | ✅ | Attach/Detach Products |
| Offerings | ✅ | ✅ | ✅ | ✅ | ✅ | Set Default |
| Packages | ✅ | ✅ | ✅ | ✅ | ✅ | Attach/Detach Products |
| Paywalls | - | - | ✅ | - | - | - |
| Subscriptions | ✅ | ✅ | - | - | - | Cancel, Refund, Get Management URL, List Transactions |
| Purchases | ✅ | ✅ | - | - | - | Refund |
| Invoices | ✅ | - | - | - | - | Get File URL |
| Charts | - | ✅ | - | - | - | Get Overview Metrics |
| Virtual Currency | ✅ | - | ✅ | ✅ | - | - |
Requirements
- .NET 8.0 or higher
- RevenueCat API v2 key
Migration from v1.x
See MIGRATION.md for detailed migration instructions from version 1.x to 2.0.
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Author
frknlkn - GitHub
Support
For issues and questions:
- GitHub Issues: Create an issue
- RevenueCat Documentation: https://www.revenuecat.com/docs/api-v2
- Examples: examples/
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.0)
- Polly (>= 8.2.0)
- Polly.Extensions.Http (>= 3.0.0)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Major v2.0.0 release with complete API coverage: 50+ new models, 20+ enums, comprehensive service methods, pagination, expandable fields, search functionality, virtual currency support, subscription lifecycle management, enhanced error handling with typed exceptions, and extensive documentation. See CHANGELOG.md for full details and MIGRATION.md for upgrade guide.