Introducing the Outseta Dart API Client: Powering Membership Businesses with Dart
Introducing the new Outseta Dart API Client, a powerful library that gives Dart and Flutter developers a clean, type-safe interface to the entire Outseta ecosystem.

Building a membership business shouldn't require juggling a dozen different tools. Outseta solves this by offering a comprehensive "Membership Operating System" that handles payments, authentication, content gating, CRM, email marketing, and more—all in one platform.
Today, I'm introducing the new Outseta Dart API Client, a powerful library that gives Dart and Flutter developers a clean, type-safe interface to the entire Outseta ecosystem.

Understanding Outseta's Ecosystem
Before diving into the API client, it's worth understanding what Outseta is and why it matters for membership businesses. Outseta positions itself as an all-in-one membership stack, perfect for membership sites, SaaS products, courses, and communities. It eliminates the need to stitch together multiple tools with complex integrations, reducing technical debt and simplifying operations.
Key components of the Outseta platform include:
- Payments: Seamless Stripe integration for subscriptions, one-time products, free trials, team billing, and various payment methods
- CRM: Customer relationship management with comprehensive member data
- Email: Marketing, transactional, and product emails with high deliverability
- Help Desk: Customer support via live chat, tickets, and knowledge base
- Auth and Protected Content: User authentication and content access control
- Reporting: Subscription metrics and member engagement analytics
For businesses building with Dart and Flutter, having a native API client that speaks directly to Outseta's services streamlines development and makes integration significantly easier.
Introducing the Outseta Dart API Client
The Outseta Dart API Client is a comprehensive, type-safe interface to the Outseta REST API v1. It provides access to all of Outseta's core functionalities through a clean, intuitive API design that follows Dart best practices.

Key Features
- Complete API Coverage: Access all major Outseta modules - CRM, Billing, Marketing, Support, and User Profile
- Type Safety: Fully typed models with JSON serialization support
- Authentication Options: Support for API key auth (server-side) and bearer token auth (client-side)
- Pagination Support: Built-in handling for Outseta's paginated responses
- Error Handling: Typed exceptions for different error scenarios
- Comprehensive Documentation: Detailed documentation and examples
Getting Started
Adding the Outseta Dart API Client to your project is straightforward. Start by adding the dependency to your pubspec.yaml
:
dependencies:
outseta: ^1.0.0
Then run:
dart pub get
Client Initialization
The client can be initialized with either API key authentication (for server-side applications) or bearer token authentication (for client-side applications):
import 'package:outseta/outseta.dart';
// For server-side usage with API keys
final client = OutsetaClient(
baseUrl: 'https://your-domain.outseta.com/api/v1',
auth: ApiKeyAuth(
apiKey: 'your-api-key',
secretKey: 'your-secret-key',
),
);
// For client-side usage with bearer token
final client = OutsetaClient(
baseUrl: 'https://your-domain.outseta.com/api/v1',
auth: BearerTokenAuth(
accessToken: 'user-access-token',
),
);
Working with Outseta's Core Modules
Let's explore how to interact with each of Outseta's main modules through the Dart API client.
CRM Module

The CRM module allows you to manage people, accounts, and deals:
// Get a list of people
final peopleResponse = await client.crm.getPeople(limit: 10);
for (final person in peopleResponse.items) {
print('${person.fullName} (${person.email})');
}
// Get a specific account
final account = await client.crm.getAccount('account-uid');
print(account.name);
// Create a new person
final newPerson = Person(
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
);
final createdPerson = await client.crm.createPerson(newPerson);
// Add a person to an account
await client.crm.addPersonToAccount('account-uid', 'person-uid');
Billing Module

The billing module provides access to plans, subscriptions, invoices, and payments:
// Get available plans
final plansResponse = await client.billing.getPlans();
for (final plan in plansResponse.items) {
print('${plan.name}: \$${plan.amount} per ${plan.billingTerm?.toLowerCase()}');
}
// Get a specific subscription
final subscription = await client.billing.getSubscription('subscription-uid');
print('Subscription status: ${subscription.status}');
// Create a new subscription
final newSubscription = Subscription(
accountUid: 'account-uid',
planUid: 'plan-uid',
startDate: DateTime.now(),
);
final createdSubscription = await client.billing.createSubscription(newSubscription);
// Get recent invoices
final invoicesResponse = await client.billing.getInvoices(limit: 5);
for (final invoice in invoicesResponse.items) {
print('Invoice #${invoice.invoiceNumber}: \$${invoice.total} (${invoice.status})');
}
Marketing Module

The marketing module enables working with email lists, campaigns, and subscribers:
// Get email lists
final listsResponse = await client.marketing.getLists();
for (final list in listsResponse.items) {
print('${list.name}: ${list.subscriberCount} subscribers');
}
// Create a new email list
final newList = EmailList(
name: 'Newsletter Subscribers',
description: 'People who want to receive our monthly newsletter',
);
final createdList = await client.marketing.createList(newList);
// Add a subscriber to the list
await client.marketing.addSubscriber(
createdList.uid!,
'person-uid-here',
);
// Create and schedule an email campaign
final emailCampaign = Email(
subject: 'Monthly Newsletter - January',
fromName: 'Your Company',
fromEmail: 'newsletter@example.com',
content: '<h1>January Newsletter</h1><p>Here are our updates...</p>',
emailListUid: createdList.uid,
);
final createdEmail = await client.marketing.createEmail(emailCampaign);
// Schedule the email to be sent
final tomorrow = DateTime.now().add(Duration(days: 1));
await client.marketing.scheduleEmail(createdEmail.uid!, tomorrow);
Support Module

The support module handles tickets, comments, and ticket management:
// Create a support ticket
final ticket = Ticket(
subject: 'Help needed',
description: 'I need help with my account',
priority: 'Medium',
);
final createdTicket = await client.support.createTicket(ticket);
// Add a comment to a ticket
await client.support.addComment(
createdTicket.uid!,
'This is a comment',
isPrivate: true,
);
// Change the status of a ticket
await client.support.changeStatus(createdTicket.uid!, 'In Progress');
// Assign a ticket to a support agent
await client.support.assignTicket(createdTicket.uid!, 'support-agent-uid');
// Get tickets assigned to a specific person
final assignedTickets = await client.support.getTicketsAssignedToPerson(
'support-agent-uid',
limit: 10,
);
print('Found ${assignedTickets.metadata.total} assigned tickets');
User Profile Module

The user profile module manages user authentication and profiles:
// Get the current user's profile
final currentUser = await client.userProfile.getCurrentUser();
print('Logged in as: ${currentUser.email}');
// Update a user's profile
final updatedUser = currentUser.copyWith(
firstName: 'New First Name',
);
await client.userProfile.updateCurrentUser(updatedUser);
// Change a user's password
await client.userProfile.changePassword(
'current-password',
'new-password',
'new-password',
);
// Request a password reset for a user
await client.userProfile.requestPasswordReset('user@example.com');
// Get an access token for client-side authentication
final token = await client.userProfile.getAccessToken(
'username@example.com',
'password',
);
print('Access token: $token');
Handling Pagination
All list endpoints in the Outseta API return paginated responses. The client makes handling this pagination straightforward:
// Get the first page of people
final firstPage = await client.crm.getPeople(offset: 0, limit: 10);
print('Total people: ${firstPage.metadata.total}');
print('Current page size: ${firstPage.metadata.count}');
print('Offset: ${firstPage.metadata.offset}');
// Get the next page
if (firstPage.metadata.total > firstPage.metadata.offset + firstPage.metadata.count) {
final nextPage = await client.crm.getPeople(
offset: firstPage.metadata.offset + firstPage.metadata.count,
limit: 10,
);
print('Next page has ${nextPage.items.length} items');
}
Handling Errors
The client provides typed exceptions for different error scenarios, making error handling clean and predictable:
try {
await client.crm.getPerson('invalid-uid');
} on NotFoundException catch (e) {
print('Person not found: ${e.message}');
} on UnauthorizedException catch (e) {
print('Authentication error: ${e.message}');
} on ApiException catch (e) {
print('API error: ${e.message}');
}
Real-World Use Cases
Let's explore some real-world use cases where the Outseta Dart API Client shines:
Building a Mobile Membership App
For businesses developing a Flutter app for their members, the Outseta Dart API Client provides a seamless way to integrate with their existing Outseta account. Members can log in, view their subscription details, update their profile, and access support right from the mobile app.
// Authenticate a user and store their access token
Future<void> loginUser(String email, String password) async {
try {
final token = await client.userProfile.getAccessToken(email, password);
// Store the token securely
await secureStorage.write(key: 'access_token', value: token);
// Update the client with the new token
updateClientAuth(BearerTokenAuth(accessToken: token));
// Fetch the user profile
final user = await client.userProfile.getCurrentUser();
// Store user info or navigate to dashboard
navigateToDashboard(user);
} catch (e) {
showLoginError(e.toString());
}
}
Managing Member Subscriptions
Subscription management is simplified with the Billing API, allowing your app to display subscription details, handle upgrades/downgrades, and process payments:
// Get available plans and current subscription
Future<void> loadSubscriptionData() async {
try {
final user = await client.userProfile.getCurrentUser();
// Get current subscription if exists
if (user.subscriptionUid != null) {
final subscription = await client.billing.getSubscription(user.subscriptionUid!);
displaySubscriptionDetails(subscription);
}
// Load available plans
final plans = await client.billing.getPlans(filter: 'IsActive eq true');
displayAvailablePlans(plans.items);
} catch (e) {
showError(e.toString());
}
}
// Change subscription plan
Future<void> changePlan(String newPlanUid) async {
try {
final user = await client.userProfile.getCurrentUser();
if (user.subscriptionUid != null) {
// Update the subscription with new plan
final updatedSubscription = await client.billing.updateSubscription(
Subscription(
uid: user.subscriptionUid,
planUid: newPlanUid,
),
);
showSuccess('Subscription updated successfully!');
displaySubscriptionDetails(updatedSubscription);
}
} catch (e) {
showError(e.toString());
}
}
Building a Support Ticketing Interface
Creating a support interface for your app is straightforward with the Support API:
// Load user's support tickets
Future<void> loadUserTickets() async {
try {
final user = await client.userProfile.getCurrentUser();
final tickets = await client.support.getTicketsSubmittedByPerson(
user.uid!,
limit: 20,
);
displayTickets(tickets.items);
} catch (e) {
showError(e.toString());
}
}
// Submit a new support ticket
Future<void> submitTicket(String subject, String description) async {
try {
final ticket = Ticket(
subject: subject,
description: description,
priority: 'Medium',
);
final createdTicket = await client.support.createTicket(ticket);
showSuccess('Ticket submitted successfully!');
navigateToTicketDetails(createdTicket);
} catch (e) {
showError(e.toString());
}
}
Implementation Details
The Outseta Dart API Client is built with a focus on clean architecture, type safety, and developer experience. Here's a glimpse into its implementation:
Client Architecture
The client is structured around a central OutsetaClient
class that handles HTTP requests and authentication, with dedicated API modules for each functional area:
// The main client for interacting with the Outseta API
class OutsetaClient {
// CRM API module for managing people, accounts, deals, etc.
late final CrmApi crm;
// Billing API module for managing subscriptions, invoices, etc.
late final BillingApi billing;
// Marketing API module for managing lists, campaigns, etc.
late final MarketingApi marketing;
// Support API module for managing tickets, knowledge base, etc.
late final SupportApi support;
// User Profile API module for managing user profiles
late final UserProfileApi userProfile;
// ... implementation details
}
Authentication Methods
Two authentication methods are supported:
/// API key authentication for server-side use
class ApiKeyAuth implements OutsetaAuth {
// ... implementation details
}
/// Bearer token authentication for client-side use
class BearerTokenAuth implements OutsetaAuth {
// ... implementation details
}
Model Design
Models are fully typed with JSON serialization support:
/// Person model representing a contact in the Outseta CRM
@JsonSerializable()
class Person extends BaseModelWithMetadata {
// ... properties and methods
/// Factory constructor that creates a [Person] from JSON data
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
/// Converts this person instance to a JSON map
@override
Map<String, dynamic> toJson() => _$PersonToJson(this);
/// Creates a copy of this person with the given fields replaced with new values
Person copyWith({
// ... parameters
}) {
// ... implementation
}
}
Comprehensive Testing
The Outseta Dart API Client comes with an extensive test suite (264 unit tests) that ensures reliability and stability. Every component of the library undergoes rigorous testing:
- Authentication Tests: Both API Key and Bearer Token authentication methods are thoroughly tested
- API Module Tests: Each API module (CRM, Billing, Marketing, Support, User Profile) has comprehensive tests for all operations
- Exception Handling: All error scenarios and exception types have dedicated tests
- Model Tests: Serialization, deserialization, equality comparison, and copying of models are fully tested
- Integration Tests: Optional integration tests can be run against real Outseta environments
The test coverage (currently 93.8 %) is consistently maintained at a high level, with many tests using mocks to simulate the Outseta API responses. This ensures that the library behaves correctly even when faced with unexpected API behavior.
Benefits for Membership Businesses
The Outseta Dart API Client offers several key benefits for membership businesses:
- Reduced Development Time: Integration with Outseta becomes a matter of hours rather than days or weeks
- Simplified Stack: Replace multiple complex integrations with a single API client
- Native Mobile Experience: Build native Flutter apps that connect seamlessly to your Outseta backend
- Type Safety: Catch errors at compile time rather than runtime
- Future-Proof: As Outseta evolves, the client will be updated to support new features as it is being used in commercial products
- Reliability: Comprehensive testing ensures the client works as expected in all scenarios
- Permissive License: The Dart API Client is published as OSS and distributed under the MIT license
Wrapping up
The Outseta Dart API Client represents a significant step forward for membership businesses building with Dart and Flutter. By providing a type-safe, comprehensive interface to Outseta's powerful platform, it enables developers to create seamless experiences for their members across web and mobile applications.
Whether you're building a SaaS product, membership site, online course, or community, the combination of Outseta's all-in-one platform and the Dart API Client's elegant integration capabilities offers a compelling solution for managing your membership business.
For businesses looking to simplify their tech stack while delivering exceptional member experiences, the Outseta Dart API Client is definitely worth exploring. The days of stitching together multiple tools with complex integrations are over - with Outseta and the Dart API Client, you can focus on what matters most: delivering value to your members.
Some of the links on this page are affiliate links. This means that if you click through and make a purchase, I may earn a commission — at no additional cost to you. I only recommend products I genuinely use or believe in.
