CallKitNet

A powerful, developer-friendly networking package built on top of Dio for Flutter and Dart applications.

CallKitNet simplifies API integration by providing authentication, automatic logging, retry mechanisms, refresh token support, model parsing, file uploads/downloads, request cancellation, and centralized error handling — all with a clean and type-safe API.


✨ Features

  • 🚀 Built on top of Dio
  • 📝 Automatic Request Logging
  • ✅ Automatic Response Logging
  • ❌ Automatic Error Logging
  • 📋 Automatic cURL Generation
  • 🔐 Authentication Support
  • 🔄 Refresh Token Support
  • 🔁 Automatic Retry Mechanism
  • 📦 Generic Model Parsing
  • 🛡 Safe Result API
  • 📤 File Upload Support
  • 📈 Upload Progress Tracking
  • 📥 File Download Support
  • 📊 Download Progress Tracking
  • ⛔ Request Cancellation
  • ⚠️ Centralized Error Handling
  • 🎯 Type-Safe API Calls
  • 📱 Flutter & Dart Compatible

Installation

Add the package to your pubspec.yaml:

dependencies:
  callkitnet: ^1.0.0

Install dependencies:

flutter pub get

Import the package:

import 'package:callkitnet/callkitnet.dart';

Quick Start

Create an API client:

final api = CallKitClient(
  config: const CallKitConfig(
    baseUrl: 'https://api.example.com',
  ),
);

Create a Model

class User {
  final int id;
  final String name;
  final String email;

  User({
    required this.id,
    required this.name,
    required this.email,
  });

  factory User.fromJson(
    Map<String, dynamic> json,
  ) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
    );
  }
}

GET Request

Fetch a single object and parse it into a model.

final user = await api.get<User>(
  path: '/users/1',
  fromJson: User.fromJson,
);

print(user.name);

GET Raw JSON

If fromJson is not provided, CallKitNet returns raw JSON.

final response = await api.get(
  path: '/users/1',
);

print(response);

GET List Request

Fetch and parse a list of objects.

final users = await api.getList<User>(
  path: '/users',
  fromJson: User.fromJson,
);

for (final user in users) {
  print(user.name);
}

POST Request

await api.post(
  path: '/login',
  body: {
    'email': 'test@gmail.com',
    'password': '123456',
  },
);

PUT Request

await api.put(
  path: '/users/1',
  body: {
    'name': 'Sanket',
  },
);

PATCH Request

await api.patch(
  path: '/users/1',
  body: {
    'name': 'Updated Name',
  },
);

DELETE Request

await api.delete(
  path: '/users/1',
);

Authentication

Save an access token:

api.saveToken(
  'your_access_token',
);

Every request automatically includes:

Authorization: Bearer your_access_token

Clear the token:

api.clearToken();

Refresh Token Support

Automatically refresh expired tokens and retry failed requests.

final api = CallKitClient(
  config: const CallKitConfig(
    baseUrl: 'https://api.example.com',
  ),
  refreshTokenHandler: RefreshTokenHandler(
    callback: () async {
      return await authRepository.refreshToken();
    },
  ),
);

When the server returns:

401 Unauthorized

CallKitNet automatically:

  • Refreshes the token
  • Saves the new token
  • Retries the original request

Safe Result API

Avoid repetitive try-catch blocks.

final result = await api.safeGet<User>(
  path: '/profile',
  fromJson: User.fromJson,
);

result.when(
  success: (user) {
    print(user.name);
  },
  failure: (message, statusCode) {
    print(message);
  },
);

File Upload

Upload a single file:

await api.upload.uploadFile(
  path: '/upload',
  file: imageFile,
);

Upload multiple files:

await api.upload.uploadFiles(
  path: '/upload',
  files: [
    image1,
    image2,
    image3,
  ],
);

Track upload progress:

await api.upload.uploadFile(
  path: '/upload',
  file: imageFile,
  onProgress: (
    sent,
    total,
  ) {
    final progress =
        (sent / total) * 100;

    print(
      'Upload: ${progress.toStringAsFixed(0)}%',
    );
  },
);

File Download

Download a file:

await api.download.download(
  url: fileUrl,
  savePath: savePath,
);

Track download progress:

await api.download.download(
  url: fileUrl,
  savePath: savePath,
  onProgress: (
    received,
    total,
  ) {
    final progress =
        (received / total) * 100;

    print(
      'Download: ${progress.toStringAsFixed(0)}%',
    );
  },
);

Request Cancellation

Create a cancellation token:

final token =
    RequestCanceller.create(
  'users',
);

Attach the token:

await api.dio.get(
  '/users',
  cancelToken: token,
);

Cancel the request:

RequestCanceller.cancel(
  'users',
);

Error Handling

All network exceptions are converted into CallKitException.

try {
  final user = await api.get<User>(
    path: '/profile',
    fromJson: User.fromJson,
  );
} on CallKitException catch (e) {
  print(e.message);
  print(e.statusCode);
}

Logging

CallKitNet automatically logs:

  • 🚀 Requests
  • ✅ Responses
  • ❌ Errors
  • 📋 cURL Commands

Example output:

🚀 REQUEST
GET https://api.example.com/users

📋 CURL
curl -X GET https://api.example.com/users

✅ RESPONSE
200 OK

❌ ERROR
404 Not Found

Enable logging:

final api = CallKitClient(
  config: const CallKitConfig(
    baseUrl: 'https://api.example.com',
  ),
  options: const CallKitOptions(
    enableLogs: true,
    printCurl: true,
  ),
);

Retry Requests

Automatically retry failed requests.

final api = CallKitClient(
  config: const CallKitConfig(
    baseUrl: 'https://api.example.com',
  ),
  options: const CallKitOptions(
    enableRetry: true,
    retryCount: 3,
  ),
);

Roadmap

Version 1.1

  • Persistent Token Storage
  • Local Cache Layer
  • Pagination Helpers
  • Request Transformers
  • Response Transformers
  • API Inspector UI

Version 1.2

  • Offline First Support
  • Request Queue
  • Background Sync
  • GraphQL Support

Author

Sanket C Panchal

Flutter Developer


License

MIT License

Copyright (c) 2026 Sanket C Panchal

Libraries

callkitnet