UNPKG

@unitpay/sdk

Version:

Official Node.js SDK for UnitPay - usage-based billing, invoicing, and analytics

1,603 lines (1,582 loc) 48.4 kB
/** * UnitPay SDK Types * TypeScript interfaces for all API requests and responses * * RevMax SDK compatible - users can switch from @revmax/agent-sdk with minimal changes */ /** * Log levels supported by the SDK */ type LogLevel = 'debug' | 'info' | 'warn' | 'error'; /** * Custom log handler function */ type LogHandler = (level: LogLevel, message: string, data?: unknown) => void; /** * Logging configuration options */ interface LoggingOptions { /** Whether logging is enabled */ enabled?: boolean; /** Minimum log level to output */ level?: LogLevel; /** Custom log handler function */ handler?: LogHandler; } /** * Telemetry handler function */ type TelemetryHandler = (metrics: RequestMetrics) => void; /** * Telemetry configuration options */ interface TelemetryOptions { /** Whether telemetry is enabled */ enabled?: boolean; /** Sample rate for telemetry (0-1), 1 = track every request */ sampleRate?: number; /** Custom handler for telemetry events */ handler?: TelemetryHandler; } /** * Request metrics collected for telemetry */ interface RequestMetrics { /** Unique ID for the request */ requestId: string; /** Request method (GET, POST, etc) */ method: string; /** Normalized request path */ path: string; /** Timestamp when request started */ startTime: number; /** Timestamp when request ended */ endTime?: number; /** Duration of the request in milliseconds */ duration?: number; /** HTTP status code */ statusCode?: number; /** Whether the request was successful */ success?: boolean; /** Error message if request failed */ errorMessage?: string; /** Error type if request failed */ errorType?: string; /** Number of retry attempts */ retryCount?: number; } /** * Telemetry statistics */ interface TelemetryStats { requestCount: number; successCount: number; errorCount: number; successRate: number; averageDuration: number; errorBreakdown: Record<string, number>; } /** * Configuration options for the UnitPay client * Compatible with RevMax SDK ClientOptions */ interface UnitPayConfig { /** API key for authentication (format: revx_pk_xxx) */ apiKey: string; /** Base URL for the API */ baseUrl?: string; /** @deprecated Use baseUrl instead. Alias for RevMax compatibility */ baseURL?: string; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** Number of retry attempts for failed requests (default: 0) */ retries?: number; /** Delay between retry attempts in milliseconds (default: 300) */ retryDelay?: number; /** Custom headers to include in all requests */ headers?: Record<string, string>; /** Enable debug logging (shorthand for logging.enabled) */ debug?: boolean; /** Logging configuration */ logging?: LoggingOptions; /** Telemetry configuration for performance tracking */ telemetry?: TelemetryOptions; } /** * RevMax SDK compatible ClientOptions alias */ type ClientOptions = Omit<UnitPayConfig, 'apiKey'>; interface Organization { id: string; name: string; } interface VerifyResponse { organization: Organization; verified: boolean; createdAt: string; updatedAt: string; } /** * A single usage record to be tracked * Compatible with RevMax SDK UsageRecord */ interface UsageRecord { /** Customer's external ID in your system */ customerExternalId: string; /** ID of the agent/product being used */ agentId: string; /** Name of the signal/metric being tracked (RevMax: signalName) */ signalName?: string; /** @deprecated Use signalName instead. Alias for RevMax compatibility */ metricName?: string; /** Quantity to record (must be >= 0) */ quantity?: number; /** Optional date for the usage event (defaults to now) */ usageDate?: string | Date; /** Optional metadata to attach to the usage event */ metadata?: Record<string, unknown>; } /** * Parameters for tracking events - supports single record or batch * Compatible with RevMax SDK TrackEventParams */ type TrackEventParams = UsageRecord | { records: UsageRecord[]; }; /** * Response for a single tracked event * Compatible with RevMax SDK SingleEventResponse */ interface SingleEventResponse { /** ID of the recorded usage */ id: string; /** Whether the recording was successful */ success: boolean; /** Additional response data */ [key: string]: unknown; } /** * Response for batch event tracking * Compatible with RevMax SDK BatchEventResponse */ interface BatchEventResponse { /** Whether the batch operation was successful */ success: boolean; /** Total number of records processed */ totalRecords: number; /** Number of records successfully processed */ successCount: number; /** Number of records that failed to process */ failureCount: number; /** Results for each record */ results: Array<{ /** Whether this record was successfully processed */ success: boolean; /** The data for the record, if successful */ responseData?: SingleEventResponse; /** Error message if the record failed */ error?: string; /** The original data that was submitted */ originalData?: Record<string, unknown>; }>; } /** * Response from event tracking - can be single or batch * Compatible with RevMax SDK TrackEventResponse */ type TrackEventResponse = SingleEventResponse | BatchEventResponse; interface UsageRecordSuccess { customerExternalId: string; agentId: string; signalName: string; quantity: number; eventId: string; rawEventId: string; timestamp: string; } interface UsageRecordFailure { record: UsageRecord; error: string; } interface UsageRecordResponse { processed: number; successful: number; failed: number; results: { success: UsageRecordSuccess[]; failed: UsageRecordFailure[]; }; } type CustomerStatus = 'active' | 'inactive' | 'suspended'; /** * Data for creating a new customer * Compatible with RevMax SDK CustomerCreateParams */ interface CreateCustomerData { /** Customer name (required) */ name: string; /** Unique external ID in your system */ externalId?: string; /** Customer email address */ email?: string; /** Customer phone number */ phone?: string; /** Customer timezone (default: UTC) */ timezone?: string; /** Customer status */ status?: CustomerStatus; /** Billing contact name */ billingContactName?: string; /** Billing contact email */ billingContactEmail?: string; /** Net payment terms in days (default: 30) */ netTerms?: number; /** List of email addresses to receive invoices */ invoiceEmailRecipients?: string[]; /** Custom metadata */ metadata?: Record<string, unknown>; /** Agent ID - if provided, auto-creates a subscription */ agentId?: string; } /** RevMax SDK compatible alias */ type CustomerCreateParams = CreateCustomerData; /** * Data for updating an existing customer * Compatible with RevMax SDK CustomerUpdateParams */ interface UpdateCustomerData { name?: string; email?: string; phone?: string; timezone?: string; status?: CustomerStatus; billingContactName?: string; billingContactEmail?: string; netTerms?: number; invoiceEmailRecipients?: string[]; metadata?: Record<string, unknown> | null; } /** RevMax SDK compatible alias */ type CustomerUpdateParams = UpdateCustomerData; interface CustomerSubscription { id: string; status: string; startDate: string; endDate: string | null; agent: { id: string; name: string; agentCode: string; }; plan: { id: string; name: string; }; } interface Customer { id: string; name: string; externalId: string | null; email: string | null; phone: string | null; timezone: string; status: CustomerStatus; billingContactName: string | null; billingContactEmail: string | null; netTerms: number; invoiceEmailRecipients: string[]; metadata: Record<string, unknown> | null; subscriptions?: CustomerSubscription[]; createdAt: string; updatedAt: string; } /** * Parameters for listing customers * Compatible with RevMax SDK CustomerListParams */ interface CustomerListParams { /** Page number for pagination */ page?: number; /** Number of items per page */ limit?: number; /** Filter by external ID */ externalId?: string; /** Filter by email */ email?: string; /** Search query string */ query?: string; } /** * Response for customer listing * Compatible with RevMax SDK CustomerListResponse */ interface CustomerListResponse { /** Array of customers */ data: Customer[]; /** Total number of results */ totalResults: number; /** Current page number */ page: number; /** Number of items per page */ limit: number; /** Whether there's a next page */ hasMore: boolean; } type InvoiceStatus = 'draft' | 'issued' | 'pending' | 'paid' | 'overdue' | 'void'; interface InvoiceLineItem { id: string; description: string; quantity: number; unitPrice: string; amount: string; signalName?: string; } interface InvoiceCustomer { id: string; name: string; email: string | null; externalId: string | null; } interface Invoice { id: string; invoiceNumber: string; status: InvoiceStatus; invoiceDate: string; dueDate: string; totalAmount: string; amountPaid: string; amountDue: string; currency: string; customer: InvoiceCustomer; lineItems: InvoiceLineItem[]; createdAt: string; } interface InvoiceDetail extends Invoice { payments?: Array<{ id: string; amount: string; paymentDate: string; paymentMethod: string; }>; subscription?: { id: string; status: string; agent: { id: string; name: string; }; plan: { id: string; name: string; }; }; } interface ListInvoicesParams { /** Filter by customer ID */ customerId?: string; /** Filter by customer external ID */ customerExternalId?: string; /** Filter by invoice status */ status?: InvoiceStatus; /** Page number (default: 1) */ page?: number; /** Results per page (default: 20) */ limit?: number; } interface ListInvoicesResponse { invoices: Invoice[]; page: number; limit: number; totalPages: number; totalResults: number; } type GroupBy = 'daily' | 'weekly' | 'monthly'; interface UsageAnalyticsParams { /** Start date (ISO format, required) */ startDate: string; /** End date (ISO format, required) */ endDate: string; /** Grouping interval (default: daily) */ groupBy?: GroupBy; /** Filter by customer ID */ customerId?: string; /** Filter by customer external ID */ customerExternalId?: string; /** Filter by agent ID */ agentId?: string; /** Filter by signal ID */ signalId?: string; } interface UsageAnalyticsSummary { totalEvents: number; totalQuantity: number; totalCost: number; uniqueCustomers: number; uniqueAgents: number; uniqueSignals: number; } interface UsageAnalyticsDataPoint { date: string; quantity: number; cost: number; eventCount: number; } interface UsageAnalyticsResponse { dateRange: { start: string; end: string; groupBy: GroupBy; }; summary: UsageAnalyticsSummary; data: UsageAnalyticsDataPoint[]; } type SubscriptionStatus = 'active' | 'paused' | 'cancelled' | 'ended' | 'pending'; interface SubscriptionCustomer { id: string; name: string; email: string | null; externalId: string | null; phone?: string | null; } interface SubscriptionAgent { id: string; name: string; agentCode: string; description?: string; } interface SubscriptionPlan { id: string; name: string; description?: string; features?: string[]; } interface Subscription { id: string; status: SubscriptionStatus; startDate: string; endDate: string | null; billingCycle: string; customer: SubscriptionCustomer; agent: SubscriptionAgent; plan: SubscriptionPlan; createdAt: string; } interface SubscriptionUsage { totalQuantity: number; totalEvents: number; periodStart: string; periodEnd: string; } interface SubscriptionDetail extends Subscription { timezone: string; usage: SubscriptionUsage; updatedAt: string; } interface ListSubscriptionsParams { /** Filter by customer ID */ customerId?: string; /** Filter by customer external ID */ customerExternalId?: string; /** Filter by agent ID */ agentId?: string; /** Filter by subscription status */ status?: SubscriptionStatus; /** Page number (default: 1) */ page?: number; /** Results per page (default: 20) */ limit?: number; } interface ListSubscriptionsResponse { subscriptions: Subscription[]; page: number; limit: number; totalPages: number; totalResults: number; } /** * Available features in a portal session */ type PortalFeature = 'invoices' | 'subscriptions' | 'usage' | 'profile'; /** * Parameters for creating a portal session * Requires a secret key (upay_sk_*) */ interface CreatePortalSessionParams { /** Customer ID (internal UnitPay ID) */ customerId?: string; /** Customer external ID (your system's ID) */ customerExternalId?: string; /** URL to redirect customer after portal session */ returnUrl?: string; /** Features to enable in the portal (default: all) */ features?: PortalFeature[]; } /** * Portal session response */ interface PortalSession { /** Portal session ID */ id: string; /** Object type identifier */ object: 'portal_session'; /** Full URL for the customer portal */ url: string; /** Portal session token (prtl_*) */ token: string; /** Customer ID */ customerId: string; /** Customer name */ customerName?: string; /** Customer email */ customerEmail?: string; /** Session expiration time */ expiresAt: string; /** Enabled features */ features: PortalFeature[]; /** Return URL after session */ returnUrl?: string; /** Session creation time */ createdAt: string; } /** * List portal sessions parameters */ interface ListPortalSessionsParams { /** Filter by customer ID */ customerId?: string; /** Maximum number of sessions to return */ limit?: number; /** Include expired sessions */ includeExpired?: boolean; } /** * List portal sessions response */ interface ListPortalSessionsResponse { /** Array of portal sessions */ data: PortalSession[]; /** Whether there are more results */ hasMore: boolean; } interface ApiErrorResponse { error: string; message: string; statusCode: number; details?: Record<string, unknown>; } /** * Input Validation Utilities */ /** * API key type */ type ApiKeyType = 'secret' | 'publishable'; /** * API key environment */ type ApiKeyEnvironment = 'live' | 'test'; /** * Parsed API key information */ interface ParsedApiKey { type: ApiKeyType; environment: ApiKeyEnvironment; isLegacy: boolean; } /** * Parse an API key to extract type and environment * * @param apiKey - The API key to parse * @returns Parsed key info or null if invalid format * * @example * ```typescript * const info = parseApiKey('upay_sk_live_xxx'); * // { type: 'secret', environment: 'live', isLegacy: false } * * const legacy = parseApiKey('revx_pk_xxx'); * // { type: 'secret', environment: 'test', isLegacy: true } * ``` */ declare function parseApiKey(apiKey: string): ParsedApiKey | null; /** * Check if an API key is a secret key (upay_sk_* or legacy revx_pk_*) */ declare function isSecretKey(apiKey: string): boolean; /** * Check if an API key is a publishable key (upay_pk_*) */ declare function isPublishableKey(apiKey: string): boolean; /** * HTTP Client Wrapper * Handles all API requests with proper error handling, authentication, retry logic, and telemetry */ /** * HTTP client for making API requests to UnitPay */ declare class HttpClient { private readonly client; private readonly logger; private readonly telemetry; private readonly retries; private readonly retryDelay; constructor(config: UnitPayConfig); /** * Make a request with retry logic */ private request; /** * Make a GET request */ get<T>(path: string, params?: Record<string, unknown>): Promise<T>; /** * Make a POST request */ post<T>(path: string, data?: unknown): Promise<T>; /** * Make a PUT request */ put<T>(path: string, data?: unknown): Promise<T>; /** * Make a PATCH request */ patch<T>(path: string, data?: unknown): Promise<T>; /** * Make a DELETE request */ delete<T = void>(path: string): Promise<T>; /** * Get telemetry statistics */ getTelemetryStats(): TelemetryStats; /** * Reset telemetry statistics */ resetTelemetryStats(): void; } /** * Usage Resource * Handles usage tracking and event recording * * RevMax SDK compatible - includes trackEvent method */ /** * Resource for recording usage events * Compatible with RevMax SDK Usage resource */ declare class UsageResource { private readonly http; constructor(http: HttpClient); /** * Track events for a customer - supports both single record and batch operations * Compatible with RevMax SDK trackEvent method * * @param params - Event tracking parameters (single record or batch) * @returns Tracked event data * * @example * ```typescript * // Single event * await client.usage.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * signalName: 'api_call', * quantity: 1 * }); * * // With metadata and usage cost (RevMax compatible) * await client.usage.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * metricName: 'meeting_booked', * metadata: { * usageCost: [ * { serviceName: 'SST-DeepGram', units: 10 }, * { serviceName: 'TTS-ElevanLabs', units: 10 } * ] * } * }); * * // Batch tracking * await client.usage.trackEvent({ * records: [ * { customerExternalId: 'cust_1', agentId: 'agent_123', signalName: 'api_call', quantity: 10 }, * { customerExternalId: 'cust_2', agentId: 'agent_123', signalName: 'storage', quantity: 100 } * ] * }); * ``` */ trackEvent(params: TrackEventParams): Promise<TrackEventResponse>; /** * Record a single usage event * UnitPay native method * * @param record - The usage record to track * @returns The response containing processing results * * @example * ```typescript * const result = await client.usage.record({ * customerExternalId: 'cust_123', * agentId: 'agent_abc', * signalName: 'api_call', * quantity: 1, * metadata: { model: 'gpt-4' } * }); * ``` */ record(record: UsageRecord): Promise<UsageRecordResponse>; /** * Record multiple usage events in a batch * UnitPay native method * * @param records - Array of usage records to track * @returns The response containing processing results for all records * * @example * ```typescript * const result = await client.usage.recordBatch([ * { customerExternalId: 'cust_123', agentId: 'agent_abc', signalName: 'api_call', quantity: 5 }, * { customerExternalId: 'cust_456', agentId: 'agent_abc', signalName: 'api_call', quantity: 3 }, * ]); * console.log(`Processed ${result.successful} of ${result.processed} records`); * ``` */ recordBatch(records: UsageRecord[]): Promise<UsageRecordResponse>; /** * Normalize a usage record, handling RevMax compatibility */ private normalizeRecord; /** * Convert UnitPay native response to RevMax BatchEventResponse format */ private convertToBatchResponse; } /** * Customers Resource * Handles customer CRUD operations * * RevMax SDK compatible - same method signatures */ /** * Resource for managing customers * Compatible with RevMax SDK Customers resource */ declare class CustomersResource { private readonly http; constructor(http: HttpClient); /** * Create a new customer * Compatible with RevMax SDK customers.create * * @param params - Customer creation parameters * @returns The created customer * * @example * ```typescript * const customer = await client.customers.create({ * name: 'Acme Corp', * externalId: 'acme_123', * email: 'billing@acme.com', * agentId: 'agent_abc' // auto-creates subscription * }); * ``` */ create(params: CreateCustomerData): Promise<Customer>; /** * Get a single customer by ID * Compatible with RevMax SDK customers.get * * @param id - The customer's ID * @returns The customer with subscriptions * * @example * ```typescript * const customer = await client.customers.get('cust_123'); * console.log(customer.name); * ``` */ get(id: string): Promise<Customer>; /** * Update an existing customer * Compatible with RevMax SDK customers.update * * @param id - The customer's ID * @param params - Fields to update * @returns The updated customer * * @example * ```typescript * const customer = await client.customers.update('cust_123', { * name: 'New Company Name', * email: 'new-email@company.com' * }); * ``` */ update(id: string, params: UpdateCustomerData): Promise<Customer>; /** * Delete a customer * Compatible with RevMax SDK customers.delete * * @param id - The customer's ID * * @example * ```typescript * await client.customers.delete('cust_123'); * ``` */ delete(id: string): Promise<void>; /** * List customers with pagination and filtering * Compatible with RevMax SDK customers.list * * @param params - List parameters * @returns Paginated list of customers * * @example * ```typescript * // RevMax compatible format * const { data, totalResults, hasMore } = await client.customers.list({ * limit: 10, * page: 1 * }); * * // Simple list (returns array for backward compatibility) * const customers = await client.customers.list(); * ``` */ list(params?: CustomerListParams): Promise<CustomerListResponse | Customer[]>; } /** * Invoices Resource * Handles invoice retrieval operations */ /** * Resource for managing invoices */ declare class InvoicesResource { private readonly http; constructor(http: HttpClient); /** * List invoices with optional filters * * @param params - Optional filter parameters * @returns Paginated list of invoices * * @example * ```typescript * const { invoices, totalResults } = await client.invoices.list({ * customerId: 'cust_123', * status: 'pending', * page: 1, * limit: 20 * }); * ``` */ list(params?: ListInvoicesParams): Promise<ListInvoicesResponse>; /** * Get a single invoice by ID * * @param invoiceId - The invoice's ID * @returns The invoice with full details including line items and payments * * @example * ```typescript * const invoice = await client.invoices.get('inv_abc'); * console.log(`Invoice ${invoice.invoiceNumber}: ${invoice.totalAmount}`); * ``` */ get(invoiceId: string): Promise<InvoiceDetail>; } /** * Analytics Resource * Handles usage analytics and reporting */ /** * Resource for accessing analytics data */ declare class AnalyticsResource { private readonly http; constructor(http: HttpClient); /** * Get usage analytics for a date range * * @param params - Analytics query parameters * @returns Usage analytics with summary and time-series data * * @example * ```typescript * const analytics = await client.analytics.usage({ * startDate: '2024-01-01', * endDate: '2024-01-31', * groupBy: 'daily', * customerId: 'cust_123' * }); * * console.log(`Total usage: ${analytics.summary.totalQuantity}`); * console.log(`Total cost: $${analytics.summary.totalCost}`); * * // Time series data * analytics.data.forEach(point => { * console.log(`${point.date}: ${point.quantity} units, $${point.cost}`); * }); * ``` */ usage(params: UsageAnalyticsParams): Promise<UsageAnalyticsResponse>; } /** * Subscriptions Resource * Handles subscription management operations */ /** * Resource for managing subscriptions */ declare class SubscriptionsResource { private readonly http; constructor(http: HttpClient); /** * List subscriptions with optional filters * * @param params - Optional filter parameters * @returns Paginated list of subscriptions * * @example * ```typescript * const { subscriptions, totalResults } = await client.subscriptions.list({ * status: 'active', * customerId: 'cust_123', * page: 1, * limit: 20 * }); * ``` */ list(params?: ListSubscriptionsParams): Promise<ListSubscriptionsResponse>; /** * Get a single subscription by ID * * @param subscriptionId - The subscription's ID * @returns The subscription with full details including usage summary * * @example * ```typescript * const sub = await client.subscriptions.get('sub_abc'); * console.log(`Status: ${sub.status}`); * console.log(`Usage this period: ${sub.usage.totalQuantity}`); * ``` */ get(subscriptionId: string): Promise<SubscriptionDetail>; } /** * Portal Sessions Resource * * Create and manage portal sessions for your customers. * Portal sessions provide secure, short-lived URLs that allow customers * to access their billing information without exposing your API key. * * This follows the Stripe/Chargebee pattern: * 1. Your backend creates a portal session using your secret key * 2. You redirect the customer to the portal URL * 3. Customer can view invoices, subscriptions, usage (1 hour expiry) * * @example * ```typescript * import { UnitPayClient } from '@unitpay/sdk'; * * const client = new UnitPayClient('upay_sk_live_your_secret_key'); * * // Create a portal session * const session = await client.portalSessions.create({ * customerId: 'cust_123', * returnUrl: 'https://myapp.com/account' * }); * * // Redirect customer to the portal * res.redirect(session.url); * ``` * * IMPORTANT: Portal session creation requires a secret key (upay_sk_*). * Publishable keys cannot create portal sessions. */ declare class PortalSessionsResource { private readonly http; private readonly assertSecretKey; constructor(http: HttpClient, assertSecretKey: () => void); /** * Create a new portal session * * Creates a short-lived portal session for a customer. * The returned URL can be used to redirect the customer to their billing portal. * * @param params - Portal session parameters * @returns Created portal session with URL and token * @throws ValidationError if neither customerId nor customerExternalId is provided * @throws AuthenticationError if using a publishable key * * @example * ```typescript * // By customer ID * const session = await client.portalSessions.create({ * customerId: 'cust_123', * returnUrl: 'https://myapp.com/account' * }); * * // By external ID * const session = await client.portalSessions.create({ * customerExternalId: 'your_customer_id', * features: ['invoices', 'usage'] * }); * * console.log(session.url); // Redirect customer here * ``` */ create(params: CreatePortalSessionParams): Promise<PortalSession>; /** * Get a portal session by ID * * @param sessionId - Portal session ID * @returns Portal session details * * @example * ```typescript * const session = await client.portalSessions.get('ps_123'); * console.log(session.expiresAt); * ``` */ get(sessionId: string): Promise<PortalSession>; /** * List portal sessions * * @param params - Optional filters * @returns List of portal sessions * * @example * ```typescript * // List all active sessions * const { data } = await client.portalSessions.list(); * * // List sessions for a specific customer * const { data } = await client.portalSessions.list({ * customerId: 'cust_123', * includeExpired: true * }); * ``` */ list(params?: ListPortalSessionsParams): Promise<ListPortalSessionsResponse>; /** * Revoke a portal session * * Immediately invalidates the session, preventing further access. * * @param sessionId - Portal session ID to revoke * * @example * ```typescript * await client.portalSessions.revoke('ps_123'); * ``` */ revoke(sessionId: string): Promise<void>; } /** * UnitPay Client * Main entry point for the UnitPay SDK * * RevMax SDK compatible - includes connect() method and trackEvent() shorthand */ /** * Organization information from API key verification * Compatible with RevMax SDK OrganizationInfo */ interface OrganizationInfo { id: string; name: string; [key: string]: unknown; } /** * UnitPay SDK Client * * Provides access to all UnitPay API resources including usage tracking, * customer management, invoicing, analytics, and subscriptions. * * RevMax SDK compatible - supports both direct instantiation and connect() pattern * * @example * ```typescript * import { UnitPayClient } from '@unitpay/sdk'; * * // RevMax-style initialization with connect() * const client = new UnitPayClient('revx_pk_your_api_key'); * await client.connect(); * * // Track an event (RevMax compatible) * await client.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * metricName: 'meeting_booked', * metadata: { * usageCost: [ * { serviceName: 'SST-DeepGram', units: 10 } * ] * } * }); * * // Or with full configuration * const client = new UnitPayClient('revx_pk_your_api_key', { * baseURL: 'https://api.custom-domain.com/v1', * timeout: 10000, * retries: 3, * retryDelay: 300, * logging: { enabled: true, level: 'info' }, * telemetry: { enabled: true, sampleRate: 1 } * }); * await client.connect(); * ``` */ declare class UnitPayClient { private readonly http; private readonly _apiKey; private readonly _keyType; private readonly _keyEnvironment; private readonly _isLegacyKey; private _orgInfo; /** * Usage tracking resource * Compatible with RevMax SDK usage resource * * @example * ```typescript * // trackEvent (RevMax compatible) * await client.usage.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * signalName: 'api_call', * quantity: 1 * }); * * // record (UnitPay native) * await client.usage.record({ * customerExternalId: 'cust_123', * agentId: 'agent_abc', * signalName: 'api_call', * quantity: 1 * }); * ``` */ readonly usage: UsageResource; /** * Customer management resource * Compatible with RevMax SDK customers resource * * @example * ```typescript * const customer = await client.customers.create({ * name: 'Acme Corp', * externalId: 'acme_123' * }); * ``` */ readonly customers: CustomersResource; /** * Invoice retrieval resource * UnitPay exclusive feature * * @example * ```typescript * const { invoices } = await client.invoices.list({ * status: 'pending' * }); * ``` */ readonly invoices: InvoicesResource; /** * Analytics resource * UnitPay exclusive feature * * @example * ```typescript * const analytics = await client.analytics.usage({ * startDate: '2024-01-01', * endDate: '2024-01-31' * }); * ``` */ readonly analytics: AnalyticsResource; /** * Subscription management resource * UnitPay exclusive feature * * @example * ```typescript * const { subscriptions } = await client.subscriptions.list({ * status: 'active' * }); * ``` */ readonly subscriptions: SubscriptionsResource; /** * Portal sessions resource * Create and manage customer portal sessions * * IMPORTANT: Requires a secret key (upay_sk_*). Publishable keys cannot create portal sessions. * * @example * ```typescript * // Create a portal session (server-side only) * const session = await client.portalSessions.create({ * customerId: 'cust_123', * returnUrl: 'https://myapp.com/account' * }); * * // Redirect customer to the portal * res.redirect(session.url); * ``` */ readonly portalSessions: PortalSessionsResource; /** * Create a new UnitPay client * Compatible with RevMax SDK constructor signature * * @param apiKeyOrConfig - Either an API key string or a configuration object * @param options - Optional client options (when first param is API key) * * @example * ```typescript * // Simple initialization * const client = new UnitPayClient('revx_pk_your_api_key'); * * // With options (RevMax style) * const client = new UnitPayClient('revx_pk_your_api_key', { * timeout: 10000, * retries: 3 * }); * * // With config object (UnitPay style) * const client = new UnitPayClient({ * apiKey: 'revx_pk_your_api_key', * baseUrl: 'https://api.example.com/v1', * debug: true * }); * ``` */ constructor(apiKeyOrConfig: string | UnitPayConfig, options?: ClientOptions); /** * Assert that the current API key is a secret key * @throws ValidationError if using a publishable key */ private assertSecretKey; /** * Connect to the UnitPay API and verify credentials * Compatible with RevMax SDK connect() method * * This must be called once before using any API methods that require verification. * Note: For UnitPay, this is optional but recommended for validating your API key. * * @returns Promise resolving to the client instance for chaining * @throws AuthenticationError if API key is invalid * @throws InitializationError for other initialization errors * * @example * ```typescript * const client = new UnitPayClient('revx_pk_your_api_key'); * * try { * await client.connect(); * console.log('Connected to UnitPay API'); * } catch (error) { * console.error('Failed to connect:', error); * } * ``` */ connect(): Promise<UnitPayClient>; /** * Verify the API key and get organization details * UnitPay native method (also works without connect()) * * @returns Verification result with organization info * * @example * ```typescript * const result = await client.verify(); * if (result.verified) { * console.log(`Connected to ${result.organization.name}`); * } * ``` */ verify(): Promise<VerifyResponse>; /** * Get organization information * Compatible with RevMax SDK getOrganization() method * * @returns Organization information from API key verification * @throws Error if organization info is not available (call connect() first) * * @example * ```typescript * await client.connect(); * const org = client.getOrganization(); * console.log(`Organization: ${org.name}`); * ``` */ getOrganization(): OrganizationInfo; /** * Track event for a customer (shorthand method) * Compatible with RevMax SDK trackEvent() method * * @param params - Event tracking parameters * @returns Tracked event data * * @example * ```typescript * // Simple event tracking * await client.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * signalName: 'api_call', * quantity: 1 * }); * * // With metadata and usage cost (RevMax compatible) * await client.trackEvent({ * agentId: 'agent_123', * customerExternalId: 'customer_456', * metricName: 'meeting_booked', * metadata: { * usageCost: [ * { serviceName: 'SST-DeepGram', units: 10 }, * { serviceName: 'TTS-ElevanLabs', units: 10 } * ] * } * }); * * // Batch tracking * await client.trackEvent({ * records: [ * { customerExternalId: 'cust_1', agentId: 'agent_123', signalName: 'api_call', quantity: 10 }, * { customerExternalId: 'cust_2', agentId: 'agent_123', signalName: 'storage', quantity: 100 } * ] * }); * ``` */ trackEvent(params: TrackEventParams): Promise<TrackEventResponse>; /** * Re-verify the API key * Compatible with RevMax SDK verifyApiKey() method * * Useful if you suspect the API key status might have changed * * @returns Updated organization information */ verifyApiKey(): Promise<OrganizationInfo>; /** * Get current telemetry statistics * Compatible with RevMax SDK getTelemetryStats() method * * @returns Telemetry statistics * * @example * ```typescript * const stats = client.getTelemetryStats(); * console.log(`Total Requests: ${stats.requestCount}`); * console.log(`Success Rate: ${(stats.successRate * 100).toFixed(2)}%`); * ``` */ getTelemetryStats(): TelemetryStats; /** * Reset telemetry statistics * Compatible with RevMax SDK resetTelemetryStats() method */ resetTelemetryStats(): void; /** * Get the API key type (secret or publishable) * * @returns 'secret' for upay_sk_* keys, 'publishable' for upay_pk_* keys * * @example * ```typescript * if (client.getKeyType() === 'secret') { * // Can create portal sessions * const session = await client.portalSessions.create({ ... }); * } * ``` */ getKeyType(): ApiKeyType; /** * Get the API key environment (live or test) * * @returns 'live' for production keys, 'test' for test keys * * @example * ```typescript * if (client.getKeyEnvironment() === 'test') { * console.log('Running in test mode'); * } * ``` */ getKeyEnvironment(): ApiKeyEnvironment; /** * Check if using a legacy API key format * * @returns true if using revx_pk_* format (deprecated) */ isLegacyKey(): boolean; /** * Check if the API key is a secret key (upay_sk_* or legacy revx_pk_*) * * @returns true if the key can perform server-side operations */ isSecretKey(): boolean; /** * Check if the API key is a publishable key (upay_pk_*) * * @returns true if the key is safe for frontend use */ isPublishableKey(): boolean; /** * Get a masked version of the API key for debugging * * @returns Masked API key showing only prefix and last 4 characters */ getMaskedApiKey(): string; } /** * UnitPay SDK Error Classes * Custom error types for different API error scenarios * * RevMax SDK compatible - includes all error types from @revmax/agent-sdk */ /** * Base error class for all UnitPay SDK errors * Compatible with RevMax SDK RevMaxError */ declare class UnitPayError extends Error { /** HTTP status code from the API response */ readonly statusCode: number; /** Error code for programmatic handling */ readonly code: string; /** Additional error details from the API */ readonly details?: Record<string, unknown>; /** Additional error metadata */ readonly metadata: Record<string, unknown>; /** Request ID associated with the error */ readonly requestId?: string; constructor(message: string, statusCode?: number, code?: string, details?: Record<string, unknown>, metadata?: Record<string, unknown>); } /** * Thrown when API authentication fails (401) * Usually indicates an invalid or expired API key * Compatible with RevMax SDK RevMaxAuthenticationError */ declare class AuthenticationError extends UnitPayError { constructor(message?: string, metadata?: Record<string, unknown>); } /** * Thrown when the API key doesn't have permission for the requested action (403) */ declare class AuthorizationError extends UnitPayError { constructor(message?: string, metadata?: Record<string, unknown>); } /** * Thrown when a requested resource is not found (404) * Compatible with RevMax SDK RevMaxNotFoundError */ declare class NotFoundError extends UnitPayError { /** The type of resource that was not found */ readonly resourceType?: string; /** The ID of the resource that was not found */ readonly resourceId?: string; constructor(message?: string, resourceType?: string, resourceId?: string, metadata?: Record<string, unknown>); } /** * Thrown when request validation fails (400/422) * Contains details about which fields failed validation * Compatible with RevMax SDK RevMaxValidationError */ declare class ValidationError extends UnitPayError { /** Object containing field-level validation errors */ readonly validationErrors?: Record<string, string[]>; constructor(message?: string, validationErrors?: Record<string, string[]>, metadata?: Record<string, unknown>); } /** * Thrown when the API rate limit is exceeded (429) * Compatible with RevMax SDK RevMaxRateLimitError */ declare class RateLimitError extends UnitPayError { /** Number of seconds to wait before retrying */ readonly retryAfter?: number; constructor(message?: string, retryAfter?: number, metadata?: Record<string, unknown>); } /** * Thrown when there's a conflict with the current state (409) * e.g., trying to create a resource that already exists */ declare class ConflictError extends UnitPayError { constructor(message?: string, metadata?: Record<string, unknown>); } /** * Thrown when a network error occurs (no response from server) */ declare class NetworkError extends UnitPayError { /** The original error that caused the network failure */ readonly originalError?: Error; constructor(message?: string, originalError?: Error, metadata?: Record<string, unknown>); } /** * Thrown when a request times out */ declare class TimeoutError extends UnitPayError { /** The timeout value in milliseconds that was exceeded */ readonly timeoutMs?: number; constructor(message?: string, timeoutMs?: number, metadata?: Record<string, unknown>); } /** * Thrown when an internal server error occurs (500) */ declare class InternalError extends UnitPayError { constructor(message?: string, metadata?: Record<string, unknown>); } /** * Thrown when SDK initialization fails * Compatible with RevMax SDK RevMaxInitializationError */ declare class InitializationError extends UnitPayError { constructor(message?: string, metadata?: Record<string, unknown>); } /** * Generic API error * Compatible with RevMax SDK RevMaxApiError */ declare class ApiError extends UnitPayError { /** API error code if available */ readonly errorCode?: string; constructor(message?: string, statusCode?: number, errorCode?: string, metadata?: Record<string, unknown>); } /** @deprecated Use UnitPayError instead. Alias for RevMax SDK compatibility */ declare const RevMaxError: typeof UnitPayError; type RevMaxError = UnitPayError; /** @deprecated Use ApiError instead. Alias for RevMax SDK compatibility */ declare const RevMaxApiError: typeof ApiError; type RevMaxApiError = ApiError; /** @deprecated Use AuthenticationError instead. Alias for RevMax SDK compatibility */ declare const RevMaxAuthenticationError: typeof AuthenticationError; type RevMaxAuthenticationError = AuthenticationError; /** @deprecated Use RateLimitError instead. Alias for RevMax SDK compatibility */ declare const RevMaxRateLimitError: typeof RateLimitError; type RevMaxRateLimitError = RateLimitError; /** @deprecated Use ValidationError instead. Alias for RevMax SDK compatibility */ declare const RevMaxValidationError: typeof ValidationError; type RevMaxValidationError = ValidationError; /** @deprecated Use NotFoundError instead. Alias for RevMax SDK compatibility */ declare const RevMaxNotFoundError: typeof NotFoundError; type RevMaxNotFoundError = NotFoundError; /** @deprecated Use InitializationError instead. Alias for RevMax SDK compatibility */ declare const RevMaxInitializationError: typeof InitializationError; type RevMaxInitializationError = InitializationError; /** * Maps HTTP status codes to appropriate error classes */ declare function createErrorFromResponse(statusCode: number, message: string, details?: Record<string, unknown>, metadata?: Record<string, unknown>): UnitPayError; /** * Parse API error response into appropriate error object * Compatible with RevMax SDK parseApiError */ declare function parseApiError(error: unknown): UnitPayError; export { ApiError, type ApiErrorResponse, type ApiKeyEnvironment, type ApiKeyType, AuthenticationError, AuthorizationError, type BatchEventResponse, type ClientOptions, ConflictError, type CreateCustomerData, type CreatePortalSessionParams, type Customer, type CustomerCreateParams, type CustomerListParams, type CustomerListResponse, type CustomerStatus, type CustomerSubscription, type CustomerUpdateParams, type GroupBy, InitializationError, InternalError, type Invoice, type InvoiceCustomer, type InvoiceDetail, type InvoiceLineItem, type InvoiceStatus, type ListInvoicesParams, type ListInvoicesResponse, type ListPortalSessionsParams, type ListPortalSessionsResponse, type ListSubscriptionsParams, type ListSubscriptionsResponse, type LogHandler, type LogLevel, type LoggingOptions, NetworkError, NotFoundError, type Organization, type OrganizationInfo, type PortalFeature, type PortalSession, RateLimitError, type RequestMetrics, RevMaxApiError, RevMaxAuthenticationError, UnitPayClient as RevMaxClient, RevMaxError, RevMaxInitializationError, RevMaxNotFoundError, RevMaxRateLimitError, RevMaxValidationError, type SingleEventResponse, type Subscription, type SubscriptionAgent, type SubscriptionCustomer, type SubscriptionDetail, type SubscriptionPlan, type SubscriptionStatus, type SubscriptionUsage, type TelemetryHandler, type TelemetryOptions, type TelemetryStats, TimeoutError, type TrackEventParams, type TrackEventResponse, UnitPayClient, type UnitPayConfig, UnitPayError, type UpdateCustomerData, type UsageAnalyticsDataPoint, type UsageAnalyticsParams, type UsageAnalyticsResponse, type UsageAnalyticsSummary, type UsageRecord, type UsageRecordFailure, type UsageRecordResponse, type UsageRecordSuccess, ValidationError, type VerifyResponse, createErrorFromResponse, isPublishableKey, isSecretKey, parseApiError, parseApiKey };