Skip to main content

Types

The SDK provides full TypeScript type coverage for every API request and response. It also uses branded types to prevent accidentally mixing up different ID strings.

Branded IDs

Branded types add compile-time safety to string IDs. A PaymentId cannot be accidentally passed where a MerchantId is expected, even though both are strings at runtime.
import { asPaymentId, asMerchantId } from '@zendfi/sdk';

const paymentId = asPaymentId('pay_test_abc123');
const merchantId = asMerchantId('merch_xyz789');

// These are type-safe at compile time
await zendfi.getPayment(paymentId);   // works
await zendfi.getPayment(merchantId);  // type error

Available Branded Types

TypeFactoryExample
PaymentIdasPaymentId()pay_test_abc123
MerchantIdasMerchantId()merch_xyz789
InvoiceIdasInvoiceId()inv_test_abc123
SubscriptionIdasSubscriptionId()sub_abc123
InstallmentPlanIdasInstallmentPlanId()inst_abc123
PaymentLinkCodeasPaymentLinkCode()link_abc123

How Branding Works

type Brand<T, B> = T & { __brand: B };
type PaymentId = Brand<string, 'PaymentId'>;
The __brand property is a phantom type — it exists only in the type system and has zero runtime overhead. You can still use branded IDs as regular strings:
const id = asPaymentId('pay_test_abc123');
console.log(id);           // "pay_test_abc123"
console.log(id.length);    // 17
console.log(`ID: ${id}`);  // "ID: pay_test_abc123"

Enums

Environment

type Environment = 'development' | 'staging' | 'production';

ApiKeyMode

type ApiKeyMode = 'test' | 'live';

Currency

type Currency = 'USD' | 'EUR' | 'GBP';

PaymentToken

type PaymentToken = 'SOL' | 'USDC' | 'USDT';

Status Types

type PaymentStatus = 'pending' | 'confirmed' | 'failed' | 'expired';
type SubscriptionStatus = 'active' | 'canceled' | 'past_due' | 'paused';
type InstallmentPlanStatus = 'active' | 'completed' | 'defaulted' | 'cancelled';
type InvoiceStatus = 'draft' | 'sent' | 'paid';
type SplitStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'refunded';

Configuration

ZendFiConfig

interface ZendFiConfig {
  apiKey?: string;
  baseURL?: string;
  environment?: Environment;
  mode?: ApiKeyMode;
  timeout?: number;        // default: 30000
  retries?: number;        // default: 3
  idempotencyEnabled?: boolean;  // default: true
  debug?: boolean;         // default: false
}

Request Types

CreatePaymentRequest

interface CreatePaymentRequest {
  amount: number;
  currency?: Currency;          // default: 'USD'
  token?: PaymentToken;         // default: 'USDC'
  description?: string;
  customer_email?: string;
  redirect_url?: string;
  metadata?: Record<string, any>;
  split_recipients?: SplitRecipient[];
}

CreatePaymentLinkRequest

interface CreatePaymentLinkRequest {
  amount: number;
  currency?: string;
  token?: string;
  description?: string;
  max_uses?: number;
  expires_at?: string;          // ISO 8601
  metadata?: Record<string, any>;
  onramp?: boolean;             // enable fiat on-ramp
  amount_ngn?: number;          // NGN amount for exact conversion
  payer_service_charge?: boolean; // add service charge to payer
}

CreateSubscriptionPlanRequest

interface CreateSubscriptionPlanRequest {
  name: string;
  description?: string;
  amount: number;
  currency?: Currency;
  interval: 'daily' | 'weekly' | 'monthly' | 'yearly';
  interval_count?: number;      // default: 1
  trial_days?: number;          // default: 0
  metadata?: Record<string, any>;
}

CreateSubscriptionRequest

interface CreateSubscriptionRequest {
  plan_id: string;
  customer_email: string;
  customer_wallet?: string;
  metadata?: Record<string, any>;
}

CreateInstallmentPlanRequest

interface CreateInstallmentPlanRequest {
  customer_wallet: string;
  customer_email?: string;
  total_amount: number;
  installment_count: number;
  first_payment_date?: string;  // ISO 8601, default: tomorrow
  payment_frequency_days: number;
  description?: string;
  late_fee_amount?: number;
  grace_period_days?: number;   // default: 7
  metadata?: Record<string, any>;
}

CreateInvoiceRequest

interface CreateInvoiceRequest {
  customer_email: string;
  customer_name?: string;
  amount: number;
  token?: PaymentToken;
  description: string;
  line_items?: InvoiceLineItem[];
  due_date?: string;            // ISO 8601
  metadata?: Record<string, any>;
}

SplitRecipient

interface SplitRecipient {
  recipient_wallet: string;
  recipient_name?: string;
  percentage?: number;          // 0-100, sum must equal 100
  fixed_amount_usd?: number;    // alternative to percentage
  split_order?: number;
}

Response Types

Payment

interface Payment {
  id: string;
  merchant_id: string;
  amount_usd?: number;
  amount?: number;
  currency?: string;
  payment_token?: PaymentToken;
  status: PaymentStatus;
  customer_wallet?: string;
  customer_email?: string;
  description?: string;
  checkout_url?: string;
  payment_url?: string;
  qr_code?: string;
  expires_at: string;
  confirmed_at?: string;
  transaction_signature?: string;
  metadata?: Record<string, any>;
  split_ids?: string[];
  created_at?: string;
  updated_at?: string;
}
interface PaymentLink {
  link_code: string;
  merchant_id: string;
  title?: string;
  description?: string;
  amount: number;
  currency: string;
  payment_methods?: string[];
  redirect_url?: string;
  expires_at?: string;
  metadata?: Record<string, any>;
  payment_url: string;
  hosted_page_url: string;
  url: string;            // alias for hosted_page_url
  id?: string;
  token?: string;
  max_uses?: number;
  uses_count?: number;
  is_active?: boolean;
  onramp?: boolean;
  payer_service_charge?: boolean;
  created_at: string;
  updated_at: string;
}

Invoice

interface Invoice {
  id: string;
  invoice_number: string;
  merchant_id: string;
  customer_email: string;
  customer_name?: string;
  amount_usd: number;
  token: PaymentToken;
  description: string;
  line_items?: InvoiceLineItem[];
  status: InvoiceStatus;
  payment_url?: string;
  due_date?: string;
  created_at: string;
  updated_at: string;
}

Webhook Types

type WebhookEvent =
  | 'payment.created'
  | 'payment.confirmed'
  | 'payment.failed'
  | 'payment.expired'
  | 'subscription.created'
  | 'subscription.activated'
  | 'subscription.canceled'
  | 'subscription.payment_failed'
  | 'split.completed'
  | 'split.failed'
  | 'installment.due'
  | 'installment.paid'
  | 'installment.late'
  | 'invoice.sent'
  | 'invoice.paid';

interface WebhookPayload {
  event: WebhookEvent;
  timestamp: string;
  merchant_id: string;
  data: Payment | Subscription;
}

interface VerifyWebhookRequest {
  payload: string | object;
  signature: string;
  secret: string;
}

Pagination

interface PaginatedResponse<T> {
  data: T[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    total_pages: number;
  };
}