@osise/api-client
v0.0.5
Published
Official TypeScript SDK for the Osise API - connecting consumers with skilled artisans
Downloads
257
Maintainers
Readme
@osise/api-client
Official TypeScript SDK for the Osise API - connecting consumers with skilled artisans in Nigeria.
Installation
npm install @osise/api-client
# or
yarn add @osise/api-client
# or
pnpm add @osise/api-clientQuick Start
Basic Usage
import { OsiseClient, BrowserTokenStorage } from '@osise/api-client';
// Create client instance
const client = new OsiseClient({
baseUrl: 'https://api.osise.com',
storage: new BrowserTokenStorage(), // Persists tokens in localStorage
onAuthRequired: () => {
// Handle auth required (e.g., redirect to login)
window.location.href = '/login';
},
});
// Request OTP
const otpResponse = await client.auth.requestOtp({
phoneNumber: '+2348012345678',
purpose: 'Login',
});
// Verify OTP
const authResponse = await client.auth.verifyOtp({
phoneNumber: '+2348012345678',
code: '123456',
deviceId: 'unique-device-id',
deviceName: 'iPhone 15',
deviceType: 'iOS',
});
// Tokens are automatically stored and used for subsequent requests
console.log('Logged in as:', authResponse.data?.user.firstName);React Integration
import { OsiseProvider, useOsiseClient, useConsumerProfile, useMutation } from '@osise/api-client/react';
import { BrowserTokenStorage } from '@osise/api-client';
// Wrap your app with the provider
function App() {
return (
<OsiseProvider
config={{
baseUrl: 'https://api.osise.com',
storage: new BrowserTokenStorage(),
onAuthRequired: () => navigate('/login'),
}}
>
<MyApp />
</OsiseProvider>
);
}
// Use hooks in components
function Profile() {
const { data: profile, isLoading, error } = useConsumerProfile();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Welcome, {profile?.firstName}!</h1>
<p>Phone: {profile?.phoneNumber}</p>
</div>
);
}
// Use mutations for actions
function CreateJobButton() {
const client = useOsiseClient();
const { mutate, isLoading } = useMutation(
(data) => client.jobs.create(data),
{
onSuccess: (job) => {
console.log('Job created:', job.id);
},
onError: (error) => {
alert(error.message);
},
}
);
return (
<button
onClick={() => mutate({
serviceCategory: 'Plumbing',
title: 'Fix leaky faucet',
description: 'Kitchen faucet is leaking',
addressId: 'addr-123',
})}
disabled={isLoading}
>
Create Job
</button>
);
}React Native Integration
import { OsiseClient, SecureTokenStorage } from '@osise/api-client';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Create secure storage for React Native
const storage = new SecureTokenStorage(AsyncStorage);
await storage.initialize(); // Load tokens from storage
const client = new OsiseClient({
baseUrl: 'https://api.osise.com',
storage,
});API Reference
Authentication
// Request OTP
await client.auth.requestOtp({
phoneNumber: '+234...',
purpose: 'Login', // or 'Registration'
deviceId: 'optional-device-id',
});
// Verify OTP
await client.auth.verifyOtp({
phoneNumber: '+234...',
code: '123456',
deviceId: 'device-id',
deviceName: 'My Phone',
deviceType: 'Android',
});
// Register new user
await client.auth.register({
phoneNumber: '+234...',
otpCode: '123456',
firstName: 'John',
lastName: 'Doe',
role: 'Consumer',
deviceId: 'device-id',
});
// Get current user
await client.auth.getCurrentUser();
// Get active sessions
await client.auth.getSessions();
// Revoke a session
await client.auth.revokeSession('session-id');
// Logout
await client.auth.logout();
// Logout all sessions
await client.auth.logoutAll();Consumer Features
// Profile
await client.consumers.getProfile();
await client.consumers.updateProfile({ firstName: 'Jane' });
await client.consumers.uploadProfilePhoto('https://uploadcare.com/...');
// Addresses
await client.consumerAddresses.getAll();
await client.consumerAddresses.create({
label: 'Home',
street: '123 Main St',
area: 'Lekki',
city: 'Lagos',
state: 'Lagos',
latitude: 6.4541,
longitude: 3.3947,
});
await client.consumerAddresses.setDefault('address-id');
// Favorites
await client.consumers.getFavorites();
await client.consumers.addFavorite('artisan-id');
await client.consumers.removeFavorite('artisan-id');
// Notification Settings
await client.consumers.getNotificationSettings();
await client.consumers.updateNotificationSettings({
pushEnabled: true,
jobUpdates: true,
});
// NDPR Compliance
await client.consumers.exportData();
await client.consumers.requestAccountDeletion({ reason: 'Moving abroad' });Artisan Features
// Profile
await client.artisans.getProfile();
await client.artisans.updateProfile({ bio: 'Experienced plumber' });
// Documents
await client.artisans.getDocuments();
await client.artisans.submitDocument({
documentType: 'Nin',
fileUrl: 'https://...',
fileName: 'nin.pdf',
fileSize: 1024,
mimeType: 'application/pdf',
});
// Guarantors
await client.artisans.getGuarantors();
await client.artisans.addGuarantor({
fullName: 'Jane Smith',
phoneNumber: '+234...',
relationship: 'Former Employer',
occupation: 'Business Owner',
address: '456 Oak St, Lagos',
});
// Bank Account
await client.artisans.getBankAccount();
await client.artisans.setBankAccount({
bankCode: '044',
accountNumber: '0123456789',
accountName: 'John Doe',
});
// Application Status
await client.artisans.getApplicationStatus();
await client.artisans.getSkillTestSlots();
await client.artisans.bookSkillTest({ slotId: 'slot-id' });
// Availability
await client.artisanAvailability.getStatus();
await client.artisanAvailability.updateStatus({ status: 'Online' });
await client.artisanAvailability.updateWorkingHours({
workingHours: [
{ dayOfWeek: 'Monday', isWorking: true, startTime: '08:00', endTime: '17:00' },
// ...
],
});
await client.artisanAvailability.updateLocation({ latitude: 6.45, longitude: 3.39 });
// Earnings
await client.artisanEarnings.getSummary();
await client.artisanEarnings.getJobEarnings({ page: 1, pageSize: 20 });
await client.artisanEarnings.getPendingEarnings();
await client.artisanEarnings.getPayouts();
// Performance
await client.artisanPerformance.getRating();
await client.artisanPerformance.getReviews();
await client.artisanPerformance.getMetrics({ period: 'month' });
await client.artisanPerformance.getAlerts();Jobs
// Consumer - Create and manage jobs
await client.jobs.create({
serviceCategory: 'Electrical',
title: 'Fix electrical outlet',
description: 'Outlet in bedroom not working',
addressId: 'address-id',
isUrgent: true,
});
await client.jobs.list({ status: 'Pending', page: 1 });
await client.jobs.get('job-id');
await client.jobs.cancel('job-id', { reason: 'Found another solution' });
await client.jobs.getTimeline('job-id');
// Quotes
await client.jobs.getQuote('job-id');
await client.jobs.respondToQuote('job-id', { decision: 'approve' });
// Payments
await client.jobs.initiatePayment('job-id', { method: 'Card' });
await client.jobs.verifyPayment('job-id', 'payment-reference');
// Ratings
await client.jobs.submitRating('job-id', {
overall: 5,
quality: 5,
punctuality: 4,
professionalism: 5,
value: 4,
reviewText: 'Great work!',
});
// Artisan - Handle assigned jobs
await client.artisanJobs.list({ status: 'Assigned' });
await client.artisanJobs.accept('job-id');
await client.artisanJobs.decline('job-id', 'Too far away');
await client.artisanJobs.startEnRoute('job-id');
await client.artisanJobs.markArrived('job-id', { latitude: 6.45, longitude: 3.39 });
await client.artisanJobs.submitQuote('job-id', {
laborCost: 5000,
materials: [
{ item: 'Wire', quantity: 2, unitPrice: 500 },
],
estimatedDuration: '2 hours',
});
await client.artisanJobs.startWork('job-id');
await client.artisanJobs.complete('job-id', 'All fixed');Admin Features
// Dashboard
await client.adminDashboard.getStats();
// Artisan Management
await client.adminArtisans.list({ search: 'John', status: 'Active' });
await client.adminArtisans.get('artisan-id');
await client.adminArtisans.suspend('artisan-id', 'Policy violation');
await client.adminArtisans.issueStrike('artisan-id', {
type: 'QualityIssue',
reason: 'Poor workmanship reported',
severity: 'warning',
});
// Application Review
await client.adminApplications.list({ verificationStatus: 'DocumentsReview' });
await client.adminApplications.reviewDocument('artisan-id', 'doc-id', {
status: 'Approved',
});
await client.adminApplications.process('artisan-id', { action: 'approve' });
// Consumer Management
await client.adminConsumers.list({ accountType: 'Business' });
await client.adminConsumers.block('consumer-id', { reason: 'Fraud' });
await client.adminConsumers.unblock('consumer-id');
// Job Management
await client.adminJobs.list();
await client.adminJobs.assignArtisan('job-id', 'artisan-id');
await client.adminJobs.resolveDispute('job-id', 'Refund issued', 5000);
// Service Categories Management
await client.adminServiceCategories.list();
await client.adminServiceCategories.get('category-id');
await client.adminServiceCategories.create({
name: 'Landscaping',
description: 'Garden and outdoor maintenance services',
displayOrder: 10,
});
await client.adminServiceCategories.update('category-id', {
isActive: true,
displayOrder: 5,
});
await client.adminServiceCategories.delete('category-id');Location Services
// Geocode an address to coordinates
const geocodeResult = await client.location.geocode({
address: '123 Main Street',
city: 'Lagos',
state: 'Lagos',
country: 'Nigeria',
});
console.log('Coordinates:', geocodeResult.data?.latitude, geocodeResult.data?.longitude);
// Reverse geocode coordinates to address
const reverseResult = await client.location.reverseGeocode({
latitude: 6.5244,
longitude: 3.3792,
});
console.log('Address:', reverseResult.data?.formattedAddress);
// Calculate distance between two points
const distance = await client.location.calculateDistance({
originLatitude: 6.5244,
originLongitude: 3.3792,
destinationLatitude: 6.4281,
destinationLongitude: 3.4219,
});
console.log(`Distance: ${distance.data?.distanceKm} km`);
console.log(`Estimated travel time: ${distance.data?.estimatedTravelTimeMinutes} minutes`);
// Get all service areas
const areas = await client.location.getServiceAreas({
state: 'Lagos',
city: 'Lekki',
});
// Find nearby service areas
const nearby = await client.location.getNearbyAreas({
latitude: 6.5244,
longitude: 3.3792,
radiusKm: 10,
limit: 5,
});
// Check if a location is serviced
const serviceCheck = await client.location.checkServiceArea(6.5244, 3.3792);
if (serviceCheck.data?.isServiced) {
console.log('Location is serviced!');
console.log('Service Area:', serviceCheck.data.serviceArea);
} else {
console.log('Location not serviced. Nearby areas:', serviceCheck.data?.nearbyAreas);
}Error Handling
import { OsiseApiError } from '@osise/api-client';
try {
await client.auth.verifyOtp({ ... });
} catch (error) {
if (error instanceof OsiseApiError) {
if (error.isUnauthorized) {
// Token expired or invalid
} else if (error.isValidationError) {
// Validation failed - check error.errors
console.log(error.errors);
} else if (error.isRateLimited) {
// Too many requests
} else if (error.isNetworkError) {
// Network issue
} else if (error.isTimeoutError) {
// Request timed out
}
console.error(error.message, error.statusCode);
}
}TypeScript Support
All types are fully exported:
import type {
// Auth
AuthResponseDto,
UserProfileDto,
SessionDto,
// Consumer
ConsumerProfileDto,
AddressDto,
// Artisan
ArtisanProfileDto,
ApplicationStatusDto,
VerificationStatus,
// Jobs
JobRequestDto,
JobStatus,
Quote,
// Location
LocationServiceAreaDto,
GeocodeRequestDto,
GeocodeResponseDto,
ReverseGeocodeRequestDto,
ReverseGeocodeResponseDto,
CalculateDistanceRequestDto,
CalculateDistanceResponseDto,
ServiceAreaCheckResultDto,
// Admin
AdminServiceCategoryDto,
CreateServiceCategoryDto,
UpdateServiceCategoryDto,
// Common
StandardResponse,
PagedResult,
// Enums
ServiceCategory,
PaymentMethod,
AccountType,
} from '@osise/api-client';Configuration Options
const client = new OsiseClient({
// Required
baseUrl: 'https://api.osise.com',
// Optional
timeout: 30000, // Request timeout in ms
storage: new BrowserTokenStorage(), // Token storage
headers: { 'X-Custom-Header': 'value' }, // Custom headers
autoRefresh: true, // Auto refresh tokens (default: true)
// Callbacks
onError: (error) => console.error(error),
onAuthRequired: () => redirectToLogin(),
onTokenRefresh: (accessToken, refreshToken) => {
console.log('Tokens refreshed');
},
});Storage Options
// Browser (localStorage)
import { BrowserTokenStorage } from '@osise/api-client';
const storage = new BrowserTokenStorage('osise'); // optional key prefix
// React Native (AsyncStorage)
import { SecureTokenStorage } from '@osise/api-client';
const storage = new SecureTokenStorage(AsyncStorage);
await storage.initialize();
// In-memory (SSR, testing)
import { MemoryTokenStorage } from '@osise/api-client';
const storage = new MemoryTokenStorage();License
MIT
