Boltcart SDK

Type-safe Dart and Flutter SDK for the Boltcart ecommerce backend.

The package is generated from the backend OpenAPI documents and exposes a small handwritten runtime plus generated models and repositories. It is a pure Dart package, so it works in Flutter mobile, desktop, web, and server-side Dart code.

Features

  • Typed repositories grouped by backend resource, such as catalogProducts, cart, orders, customersMe, adminOrders, and auth.
  • Typed request bodies, query objects, path parameter objects, response models, and shared ProblemDetails.
  • Eden-style results with Future<ApiResult<T>>, so callers handle success and failure explicitly.
  • Auth helpers for bearer tokens, cookies, and custom async headers.
  • Dio transport with cancellation and per-request headers.
  • JSON requests and responses.
  • Multipart uploads for file endpoints.
  • PDF downloads as Uint8List.
  • Notification streams as Stream<ServerSentEvent>.

Installation

For a local monorepo Flutter or Dart app, depend on the package by path:

dependencies:
  boltcart_sdk:
    path: ../packages/boltcart_sdk

Then fetch dependencies:

dart pub get

For Flutter apps, use:

flutter pub get

Quick Start

import 'package:boltcart_sdk/boltcart_sdk.dart';

Future<void> main() async {
  final sdk = BoltcartSdk(
    baseUrl: Uri.parse('https://api.example.com'),
  );

  final result = await sdk.catalogProducts.getCatalogProducts();

  switch (result) {
    case ApiSuccess(:final data):
      for (final product in data.data) {
        print(product.title);
      }
    case ApiFailure(:final error):
      print(error.message);
  }
}

Authentication

Use a bearer token:

final sdk = BoltcartSdk(
  baseUrl: Uri.parse('https://api.example.com'),
  auth: BoltcartAuth.bearer(accessToken),
);

Use a cookie session:

final sdk = BoltcartSdk(
  baseUrl: Uri.parse('https://api.example.com'),
  auth: BoltcartAuth.cookie('better-auth.session_token=...'),
);

Use custom async headers:

final sdk = BoltcartSdk(
  baseUrl: Uri.parse('https://api.example.com'),
  auth: BoltcartAuth.headers(() async {
    final token = await secureStorage.read(key: 'access_token');
    return token == null ? {} : {'authorization': 'Bearer $token'};
  }),
);

Per-request headers can be passed with BoltcartRequestOptions:

final result = await sdk.orders.getOrders(
  options: const BoltcartRequestOptions(
    headers: {'x-boltcart-locale': 'en'},
  ),
);

Working With Results

Every generated repository method returns Future<ApiResult<T>>.

final result = await sdk.cart.getCart();

final cart = result.when(
  success: (success) => success.data,
  failure: (failure) {
    final error = failure.error;
    throw StateError(error.message);
  },
);

Success values include the decoded typed data, status code, and response headers:

if (result case ApiSuccess(:final data, :final statusCode, :final headers)) {
  print(statusCode);
  print(headers['cache-control']);
  print(data);
}

Failures are typed:

if (result case ApiFailure(:final error)) {
  switch (error) {
    case BoltcartProblemError(:final problem):
      print(problem.code);
      print(problem.detail);
    case BoltcartHttpError(:final statusCode, :final body):
      print('Unexpected HTTP $statusCode: $body');
    case BoltcartNetworkError(:final cause):
      print('Network problem: $cause');
    case BoltcartDecodeError(:final cause):
      print('Decode problem: $cause');
  }
}

Query, Params, and Body Models

Generated methods use typed objects when an endpoint has path parameters, query parameters, or a body.

final product = await sdk.catalogProducts.getCatalogProductsByHandle(
  params: const GetCatalogProductsByHandleParams(handle: 'classic-shirt'),
);
final orders = await sdk.orders.getOrders(
  query: const GetOrdersQuery(page: 1, pageSize: 20),
);
final updated = await sdk.cart.patchCartItemsById(
  params: const PatchCartItemsByIdParams(id: 'cart_item_id'),
  body: const PatchCartItemsByIdRequest(quantity: 2),
);

Model classes include:

  • fromJson
  • toJson
  • copyWith
  • deep equality

File Uploads

Multipart endpoints use Dio MultipartFile.

import 'package:dio/dio.dart';
import 'package:boltcart_sdk/boltcart_sdk.dart';

final result = await sdk.adminFiles.postAdminFiles(
  body: PostAdminFilesRequest(
    file: await MultipartFile.fromFile(
      '/path/to/image.png',
      filename: 'image.png',
      contentType: DioMediaType('image', 'png'),
    ),
  ),
);

PDF Downloads

Invoice endpoints return Uint8List.

final result = await sdk.orders.getOrdersByOrderNumberInvoicePdf(
  params: const GetOrdersByOrderNumberInvoicePdfParams(
    orderNumber: 'BC-2026-0001',
  ),
);

if (result case ApiSuccess(:final data)) {
  // `data` is Uint8List.
}

Notification Streams

Server-Sent Event endpoints return a stream wrapped in ApiResult.

final result = await sdk.customersMe.getMeNotificationsStream();

if (result case ApiSuccess(:final data)) {
  await for (final event in data) {
    print(event.event);
    print(event.data);
  }
}

Using a Custom Dio Instance

Pass a configured Dio instance when you need interceptors, custom timeouts, proxies, certificate pinning, or logging.

final dio = Dio(
  BaseOptions(
    connectTimeout: const Duration(seconds: 10),
    receiveTimeout: const Duration(seconds: 30),
  ),
);

dio.interceptors.add(LogInterceptor(responseBody: false));

final sdk = BoltcartSdk(
  baseUrl: Uri.parse('https://api.example.com'),
  dio: dio,
);

Generated Surface

The SDK currently contains generated coverage for:

  • Public catalog: products, brands, categories, reviews.
  • Buyer flows: cart, checkout, orders, returns, wishlist, customer profile, addresses, notifications.
  • Admin flows: files, catalog, customers, sellers, dashboard, inventory, notifications, orders, discounts, returns, audit logs.
  • Better Auth routes under sdk.auth.
  • System health under sdk.system.

Generated files live under lib/src/generated_sdk.dart, lib/src/model/generated_models.dart, and lib/src/repo/generated_repositories.dart.

Regenerating the SDK

From the repository root:

bun run sdk:generate

Check that generated files are current:

bun run sdk:generate:check

Run SDK tests and analysis:

bun run sdk:test
bun run sdk:analyze

The generator and test tooling are repository-only files and are excluded from pub.dev packages with .pubignore.

Publishing Notes

The pub package excludes repository-only files such as:

  • test/
  • tool/
  • openapi.generated.json
  • package.json
  • pubspec.lock
  • analysis_options.yaml

Those files remain in git for this private repository but are not intended to be part of the public pub.dev package.

Libraries

boltcart_sdk