Data Models
Reference for data structures returned by the API.
PaginatedResponse
All list endpoints return a paginated wrapper:
typescript
interface PaginatedResponse<T> {
items: T[] // Page of results
total: number // Total items matching the query
limit: number // Maximum items per page
offset: number // Number of items skipped
}Example:
json
{
"items": [ ... ],
"total": 142,
"limit": 50,
"offset": 0
}SubscribeRequest
Request body for POST /public/subscribe:
typescript
interface SubscribeRequest {
plan_id: string // Plan to subscribe to
payment_method: PaymentMethod // Desired payment method
email?: string // Subscriber email
name?: string // Subscriber display name
telegram?: string // Telegram username
nostr?: string // Nostr npub or NIP-05
receive_confirmations?: boolean // Opt in to confirmations (default: true)
receive_reminders?: boolean // Opt in to reminders (default: true)
}Plan
typescript
interface Plan {
id: string
wallet: string
name: string
description?: string
amount_sats: number
interval: 'weekly' | 'monthly' | 'yearly'
trial_days: number
grace_period_days: number
// Payment method flags
allow_lightning: boolean
allow_onchain: boolean
allow_nwc: boolean // NWC automatic payments
allow_stripe: boolean // Cards, Apple Pay, Google Pay
allow_paypal: boolean // PayPal payments
// Optional configuration
watchonly_wallet_id?: string
stripe_account_id?: string
paypal_merchant_id?: string
created_at: number
updated_at: number
is_deleted: boolean
}Subscription
typescript
interface Subscription {
id: string
plan_id: string
subscriber_id: string
status: SubscriptionStatus
current_period_start: number
current_period_end: number
trial_end?: number
cancelled_at?: number
created_at: number
updated_at: number
}
type SubscriptionStatus =
| 'pending'
| 'active'
| 'paused'
| 'past_due'
| 'payment_failed'
| 'cancelled'
| 'expired'Subscriber
typescript
interface Subscriber {
id: string
email?: string
telegram?: string
nostr?: string
name?: string
access_token: string
created_at: number
}Payment
typescript
interface Payment {
id: string
subscription_id: string
amount_sats: number
amount_fiat?: number // For Stripe/PayPal payments
currency?: string // 'usd', 'eur', etc.
status: PaymentStatus
payment_method: PaymentMethod
// Bitcoin-specific
payment_request?: string // Lightning invoice
payment_hash?: string // Lightning payment hash
onchain_address?: string // On-chain address
onchain_txid?: string // On-chain transaction ID
// Fiat-specific
stripe_payment_id?: string // Stripe payment intent ID
paypal_order_id?: string // PayPal order ID
created_at: number
paid_at?: number
}
type PaymentMethod =
| 'lightning' // Lightning Network
| 'onchain' // On-chain Bitcoin
| 'nwc' // NWC automatic payment
| 'stripe' // Stripe (cards, Apple Pay, Google Pay)
| 'paypal' // PayPal
type PaymentStatus = 'pending' | 'paid' | 'failed' | 'expired'NWC Models
Models for Nostr Wallet Connect integration.
NWC Validate Request
typescript
interface NWCValidateRequest {
nwc_string: string // The full NWC connection string
}NWC Validate Response
typescript
interface NWCValidateResponse {
valid: boolean
error?: string // Human-readable error if invalid
}NWC Subscription Create
typescript
interface NWCSubscriptionCreate {
plan_id: string
email?: string
name?: string
nwc_connection_string: string
contact_preference?: 'email' | 'telegram' | 'nostr'
}NWC Subscription Response
typescript
interface NWCSubscriptionResponse {
subscription_id: string
status: 'active' | 'pending'
message: string
error_code?: string // Only if payment failed
}NWC Connection
Internal model for stored NWC connections:
typescript
interface NWCConnection {
id: string
subscriber_id: string
wallet_pubkey: string // First 8 chars shown to user
relay_url: string
max_amount_sats?: number
is_active: boolean
last_used_at?: number
last_error?: string
consecutive_failures: number
created_at: number
updated_at?: number
}Webhook Event
typescript
interface WebhookEvent {
event: string
timestamp: number
data: {
subscription_id: string
plan_id: string
plan_name: string
subscriber_email?: string
subscriber_name?: string
status: string
amount_sats?: number
[key: string]: any
}
}API Response Models
Common response structures returned by specific endpoints.
CheckoutResponse
Returned by POST /public/subscribe for paid plans:
typescript
interface CheckoutResponse {
payment_id: string // Use this to poll payment status
payment_method: PaymentMethod
// Lightning
payment_request?: string // BOLT11 invoice
payment_hash?: string // Lightning payment hash
// On-chain
onchain_address?: string // Bitcoin address
satspay_charge_id?: string // SatsPay charge ID
bip21_uri?: string // BIP21 unified payment URI
// Fiat (Stripe/PayPal)
checkout_url?: string // Redirect URL for fiat checkout
// QR codes (pre-generated SVG strings)
qr_codes?: Record<string, string> // Keyed by mode: 'lightning', 'onchain', 'bip21'
// Expiry
expires_at: number // Unix timestamp
}TrialSubscriptionResponse
Returned by POST /public/subscribe for plans with free trials:
typescript
interface TrialSubscriptionResponse {
subscription_id: string // New subscription ID
status: 'active' // Trials are immediately active
trial: true // Always true for trial responses
trial_days: number // Length of the trial period
message: string // e.g. "Your 7-day free trial has started!"
}PaymentStatusResponse
Returned by GET /public/payment/{id}/status:
typescript
interface PaymentStatusResponse {
payment_id: string
status: string // 'pending', 'paid', 'expired'
paid_at?: number // Unix timestamp when paid
subscription_id: string
}ManageLinkResponse
Returned by GET /subscriptions/{id}/manage-link:
typescript
interface ManageLinkResponse {
subscription_id: string
subscriber_email: string
manage_url: string
}SuccessMessageResponse
Returned by cancel, disconnect, and similar operations:
typescript
interface SuccessMessageResponse {
success: boolean
message: string
}Timestamps
All timestamps are Unix timestamps (seconds since epoch).
javascript
// Convert to Date
const date = new Date(timestamp * 1000)
// Current timestamp
const now = Math.floor(Date.now() / 1000)