The PERS SDK is a platform-agnostic TypeScript library that provides a clean, modern interface for integrating with the PERS (Phygital Experience Rewards System) platform. Built with a Manager-Service architecture, it offers consistent APIs for loyalty and tokenization applications across web, mobile, and server environments.
PERS is a SaaS tokenization and loyalty infrastructure. The SDK provides access to:
- Token Operations - Balance queries, transfers, minting
- Campaign Management - Campaign discovery, claims, triggers
- User Management - Authentication, profiles, wallets
- Business Operations - Merchant and partner integrations
- Transactions - History, analytics, reporting
- File Management - Secure upload/download with signed URLs
# Core SDK + required peer dependencies
npm install @explorins/pers-sdk @explorins/pers-shared ethers@^6.15.0import { PersSDK } from "@explorins/pers-sdk";
import { BrowserFetchClientAdapter } from "@explorins/pers-sdk/platform-adapters";
const sdk = new PersSDK(new BrowserFetchClientAdapter(), {
environment: "production",
// API Project Key is used to identify the Tenant Context.
// It does NOT authenticate the user or admin.
apiProjectKey: "your-project-key"
});// Login with external JWT (Firebase, Auth0, etc.)
// This wraps the /auth/token endpoint using SessionAuthRequestDTO
await sdk.auth.loginWithToken(firebaseJWT, "user");
// Alternative: Login with raw user data (guest/anonymous users)
await sdk.auth.loginWithRawData({
externalId: "guest-123",
email: "guest@example.com",
firstName: "Guest"
});
// Check authentication status
if (await sdk.auth.isAuthenticated()) {
const user = await sdk.auth.getCurrentUser();
console.log("Welcome,", user.name);
}// Business operations
const businesses = await sdk.businesses.getActiveBusinesses();
const business = await sdk.businesses.getBusinessById("business-123");
// Campaign management
const campaigns = await sdk.campaigns.getActiveCampaigns();
const claim = await sdk.campaigns.claimCampaign({
campaignId: "campaign-123",
businessId: "business-456" // Optional business context
});
// Token operations - get available tokens
const tokens = await sdk.tokens.getTokens();
const creditToken = await sdk.tokens.getActiveCreditToken();
// Transaction history
const transactions = await sdk.transactions.getUserTransactionHistory('ALL');
// File operations
const uploadUrl = await sdk.files.getSignedPutUrl("entity-123", "profile-image", "jpg");
const downloadUrl = await sdk.files.getSignedGetUrl("entity-123", "profile-image");import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { PersSDK } from "@explorins/pers-sdk";
import { AngularHttpClientAdapter } from "@explorins/pers-sdk/platform-adapters";
@Injectable({ providedIn: "root" })
export class PersSDKService {
private sdk: PersSDK;
constructor(httpClient: HttpClient) {
this.sdk = new PersSDK(new AngularHttpClientAdapter(httpClient), {
environment: "production",
apiProjectKey: "your-project-key" // Tenant Context ID
});
}
getSDK(): PersSDK {
return this.sdk;
}
}import { PersSDK } from "@explorins/pers-sdk";
import { BrowserFetchClientAdapter } from "@explorins/pers-sdk/platform-adapters";
const sdk = new PersSDK(new BrowserFetchClientAdapter(), {
environment: "production",
apiProjectKey: "your-project-key"
});
// React Hook example
export function usePersSDK() {
return sdk;
}import { PersSDK } from "@explorins/pers-sdk";
import { NodeHttpClientAdapter } from "@explorins/pers-sdk/platform-adapters";
const sdk = new PersSDK(new NodeHttpClientAdapter(), {
environment: "production",
apiProjectKey: "your-project-key"
});The SDK follows a clean Manager-Service pattern:
- sdk.auth - Authentication and user sessions
- sdk.users - User profile management
- sdk.userStatus - User status/tier management
- sdk.tokens - Token operations and balances
- sdk.businesses - Business operations
- sdk.campaigns - Marketing campaigns
- sdk.redemptions - Reward redemptions
- sdk.transactions - Transaction history
- sdk.purchases - Purchase and payment processing
- sdk.files - File upload and management
- sdk.analytics - Reporting and insights
- sdk.tenants - Multi-tenant configuration
- sdk.apiKeys - API key management (admin)
- sdk.donations - Charitable giving and donations
- sdk.web3 - Blockchain operations and token balances
For advanced operations, you can access services directly:
const userService = sdk.users.getUserService();
const campaignService = sdk.campaigns.getCampaignService();
const fileService = sdk.files.getFileService();- External JWT integration (Firebase, Auth0, custom providers)
- Native token validation and refresh
- Support for both user and admin authentication flows
- Automatic token management and renewal
- Business registration and profile management
- Business type categorization
- Public business discovery
- Admin tools for business operations
- Create and manage marketing campaigns
- User participation and claim tracking
- Advanced campaign triggers and automation
- Analytics and performance metrics
- Multi-token support (credit, reward, utility tokens)
- Balance management and transfers
- Transaction history and analytics
- Integration with external payment systems
Important: User token balances are queried directly from the blockchain via
sdk.web3.*methods, not stored in the PERS backend. See the npm package README for detailed examples.
- Secure file upload and download
- Signed URL generation for direct browser access
- Media optimization and processing
- Cloud storage integration
- Flexible redemption offer system
- User redemption tracking
- Multiple redemption types (discounts, products, experiences)
- Inventory management
interface PersConfig {
environment?: "production"; // Currently only production is available
apiProjectKey: string; // Tenant Context Identifier (NOT for Auth)
authStorage?: TokenStorage; // Default: LocalStorage, recommend IndexedDB
dpop?: { enabled?: boolean }; // Default: true (security feature)
timeout?: number;
retries?: number;
}- production - Live environment (
https://api.pers.ninja/v2)
You can provide a custom authentication provider or let the SDK create one automatically:
// Auto-created provider (recommended)
const sdk = new PersSDK(httpClient, {
environment: "production",
apiProjectKey: "your-key"
});
// Custom provider
const sdk = new PersSDK(httpClient, {
environment: "production",
apiProjectKey: "your-key",
authProvider: customAuthProvider
});import { PersApiError, AuthenticationError } from "@explorins/pers-sdk/core";
try {
const user = await sdk.auth.getCurrentUser();
} catch (error) {
if (error instanceof AuthenticationError) {
// Handle 401 - redirect to login
} else if (error instanceof PersApiError) {
console.error("API Error:", error.message, error.status);
}
}- Bundle Size: ~85 KB minified
- Tree-shaking: Import only what you need
- Zero External Auth Dependencies: Native browser APIs
- Intelligent Token Refresh: Background refresh with race condition protection
- Request Optimization: Automatic retry and timeout handling
The SDK provides full TypeScript support with type inference. All domain types are exported from @explorins/pers-shared:
import type { CampaignDTO, BusinessDTO, TokenDTO } from '@explorins/pers-shared';
const campaigns = await sdk.campaigns.getActiveCampaigns(); // CampaignDTO[]For operations not covered by managers:
const apiClient = sdk.api();
const customData = await apiClient.get("/custom-endpoint");
await apiClient.post("/custom-endpoint", data);Implement your own HTTP client for specific requirements:
import { HttpClient, RequestOptions } from "@explorins/pers-sdk/core";
class CustomHttpClient implements HttpClient {
async get<T>(url: string, options?: RequestOptions): Promise<T> {
// Your implementation
}
// ... other methods
}
const sdk = new PersSDK(new CustomHttpClient(), config);Query token balances and owned NFTs directly from the blockchain:
// Get reward tokens configuration
const rewardTokens = await sdk.tokens.getRewardTokens();
// Query owned tokens for any wallet address
const result = await sdk.web3.getAccountOwnedTokensFromContract(
walletAddress,
rewardTokens[0]
);
console.log(`Wallet owns ${result.totalOwned} tokens`);
result.ownedTokens.forEach(token => {
console.log(`- ${token.metadata?.name}: ${token.balance}`);
});
// Get blockchain explorer URL
const explorerUrl = await sdk.web3.getExplorerUrl(
chainId,
transactionHash,
'tx'
);- @explorins/pers-sdk-react-native - React Native integration with passkey support, secure storage, and DPoP. Use this for React Native apps instead of the core SDK.
- @explorins/pers-shared - Shared types, interfaces, and DTOs used across PERS ecosystem (required peer dependency)
- Package: npm package
- Platform Documentation: PERS Platform Docs
- Support: Contact support@explorins.com for issues and feature requests
MIT License - See package for full license details.