@usebillow/sdk 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +274 -0
- package/dist/billing-C4RIMgH_.d.ts +1053 -0
- package/dist/billing-DZ4rIyg7.d.cts +1053 -0
- package/dist/billing-status-BZQN_gm7.d.cts +29 -0
- package/dist/billing-status-BZQN_gm7.d.ts +29 -0
- package/dist/chunk-CCG4F5FK.js +48 -0
- package/dist/chunk-CCG4F5FK.js.map +1 -0
- package/dist/chunk-Z6VXPONT.js +1493 -0
- package/dist/chunk-Z6VXPONT.js.map +1 -0
- package/dist/config.cjs +233 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +104 -0
- package/dist/config.d.ts +104 -0
- package/dist/config.js +228 -0
- package/dist/config.js.map +1 -0
- package/dist/credits-C3Fe3TO0.d.cts +315 -0
- package/dist/credits-C3Fe3TO0.d.ts +315 -0
- package/dist/index.cjs +1560 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2379 -0
- package/dist/index.d.ts +2379 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/ingestion.cjs +259 -0
- package/dist/ingestion.cjs.map +1 -0
- package/dist/ingestion.d.cts +182 -0
- package/dist/ingestion.d.ts +182 -0
- package/dist/ingestion.js +252 -0
- package/dist/ingestion.js.map +1 -0
- package/dist/react.cjs +360 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +71 -0
- package/dist/react.d.ts +71 -0
- package/dist/react.js +153 -0
- package/dist/react.js.map +1 -0
- package/dist/server.cjs +98 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +54 -0
- package/dist/server.d.ts +54 -0
- package/dist/server.js +96 -0
- package/dist/server.js.map +1 -0
- package/dist/status.cjs +60 -0
- package/dist/status.cjs.map +1 -0
- package/dist/status.d.cts +31 -0
- package/dist/status.d.ts +31 -0
- package/dist/status.js +3 -0
- package/dist/status.js.map +1 -0
- package/dist/webhooks.cjs +157 -0
- package/dist/webhooks.cjs.map +1 -0
- package/dist/webhooks.d.cts +391 -0
- package/dist/webhooks.d.ts +391 -0
- package/dist/webhooks.js +143 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +169 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2379 @@
|
|
|
1
|
+
import { c as TaxBehavior, d as Customer, U as UnappliedPaymentReason, S as SavedPaymentMethod, e as CreateChargeInput, R as RequestOptions, f as Charge, g as CreateMerchantInitiatedChargeInput, I as IdempotentRequestOptions, h as CallOptions, i as PayInvoiceInput, C as CreateProductInput, j as UpdateProductInput, k as MigrationResult, l as CreateSubscriptionInput, B as BillowOptions, a as CreateCouponInput, m as Coupon, F as FeatureKind, M as MeterConfig, n as Feature, o as UpdateFeatureInput, p as UsageAlert, q as CreateUsageAlertInput, b as CheckResult, T as TrackResult, E as EntitlementView, A as AttachResult } from './billing-DZ4rIyg7.cjs';
|
|
2
|
+
export { r as ActivatedSubscriptionResult, s as BillingInterval, t as ContractAddSubscriptionItemInput, u as ContractApplySubscriptionCouponInput, v as ContractCancelSubscriptionInput, w as ContractChangeSubscriptionPlanInput, x as ContractCreateChargeInput, y as ContractCreateCustomerInput, z as ContractCreateMerchantInitiatedChargeInput, D as ContractCreatePortalSessionInput, G as ContractCreateProductInput, H as ContractCreateSubscriptionInput, J as ContractCreateWebhookEndpointInput, K as ContractMigrateSubscribersInput, L as ContractRefundChargeInput, N as ContractResolveRefundInput, O as ContractUpdateProductInput, Q as ContractUpdateSubscriptionItemInput, V as ContractUpdateWebhookEndpointInput, W as CouponDuration, X as CouponKind, Y as CreateSubscriptionResult, Z as EntitlementInput, _ as InvoicePaymentResult, $ as MeterAggregation, a0 as MeterFilter, a1 as MeterRoundingMode, a2 as PendingSubscriptionCheckoutResult, a3 as PriceInput, P as Product, a4 as ProductEntitlement, a5 as ProductPrice, a6 as Subscription, a7 as SubscriptionDetail, a8 as SubscriptionItem, a9 as UpdatePriceInput, aa as UsageAlertKind, ab as UsageAlertMetric, ac as UsageModel, ad as UsageTier } from './billing-DZ4rIyg7.cjs';
|
|
3
|
+
import { C as ChargeStatus, P as PaymentMethodStatus, I as InvoiceStatus, R as RefundStatus, W as WebhookDeliveryStatus } from './billing-status-BZQN_gm7.cjs';
|
|
4
|
+
export { a as CHARGE_STATUSES, b as INVOICE_STATUSES, c as PAYMENT_METHOD_STATUSES, d as REFUND_STATUSES, e as WEBHOOK_DELIVERY_STATUSES } from './billing-status-BZQN_gm7.cjs';
|
|
5
|
+
import { SubscriptionStatus } from './status.cjs';
|
|
6
|
+
export { ACTIVE_SUBSCRIPTION_STATUSES, NEVER_ACTIVATED_SUBSCRIPTION_STATUSES, SUBSCRIPTION_STATUSES, TERMINAL_SUBSCRIPTION_STATUSES, grantsAccess, isTerminal } from './status.cjs';
|
|
7
|
+
import { a as CreditThresholdLevel, b as CreditGrant, c as CreditTopUp, d as CreateCreditGrantInput, e as CreditGrantRequestResult, f as CreditPacks, g as CreateCreditPackInput, h as CreditPack, U as UpdateCreditPackInput, i as CreateCreditTopUpInput, j as CreditTopUpRequestResult, k as CreditTopUpListParams, l as CreditBalance, m as CreditLedgerEntry, n as CreditUsageParams, o as CreditUsage } from './credits-C3Fe3TO0.cjs';
|
|
8
|
+
export { p as CreditAccountStatus, C as CreditGrantKind, q as CreditMoney, r as CreditPackListItem, s as CreditTopUpStatus, t as CreditTransactionType, u as CreditUsageGroupBy } from './credits-C3Fe3TO0.cjs';
|
|
9
|
+
import 'zod';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The machine-readable error codes billow returns on `BillowApiError.code`. Mirrored from
|
|
13
|
+
* `@billow/core`'s `BILLOW_ERROR_CODES` (the server's source of truth) — the SDK carries no
|
|
14
|
+
* runtime dependency on core, so `error-codes.test.ts` asserts this list stays in lockstep.
|
|
15
|
+
*
|
|
16
|
+
* `switch` on these for programmatic handling (e.g. surface `rate_limited` vs `validation_error`
|
|
17
|
+
* differently). The `code` field stays widened to `string` for forward-compatibility, so a code a
|
|
18
|
+
* newer server adds never breaks type-checking against an older SDK.
|
|
19
|
+
*/
|
|
20
|
+
declare const BILLOW_ERROR_CODES: readonly ["not_found", "validation_error", "authentication_error", "api_key_expired", "permission_denied", "conflict", "invalid_state_transition", "provider_error", "rate_limited", "quota_exceeded", "internal_error", "insufficient_credits", "account_frozen", "account_closed", "idempotency_conflict", "commit_exceeds_hold", "reversal_exceeds_consumption"];
|
|
21
|
+
type BillowErrorCode = (typeof BILLOW_ERROR_CODES)[number];
|
|
22
|
+
|
|
23
|
+
/** Public SDK types for this domain. Re-exported by ../types.ts. */
|
|
24
|
+
|
|
25
|
+
/** A payment provider's declarative admin surface (rendered into the credentials form). */
|
|
26
|
+
interface PaymentProviderDefinition {
|
|
27
|
+
/** Registry key + `payment_credentials.provider` discriminator (e.g. "paymob"). */
|
|
28
|
+
provider: string;
|
|
29
|
+
label: string;
|
|
30
|
+
/** Config-field manifest; secret fields are stored encrypted and never returned. */
|
|
31
|
+
fields: ConfigField[];
|
|
32
|
+
/** Customer-present checkout methods this provider can offer. */
|
|
33
|
+
methods: ("card" | "wallet" | "sympl" | "applepay")[];
|
|
34
|
+
/** Live verify targets the dashboard can "Test". */
|
|
35
|
+
verifyTargets: ProviderVerifyTarget[];
|
|
36
|
+
/**
|
|
37
|
+
* When present, the dashboard surfaces a copy-able webhook URL to register in the
|
|
38
|
+
* provider's own dashboard (e.g. Stripe). Omitted for providers that set their
|
|
39
|
+
* callback per-charge (Paymob). `events` is an optional hint list; `url` is the
|
|
40
|
+
* tenant's full endpoint, filled in by the API per (org, environment).
|
|
41
|
+
*/
|
|
42
|
+
webhook?: {
|
|
43
|
+
events?: string[];
|
|
44
|
+
url?: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** One customer-present checkout method offered for a currency (for a method picker). */
|
|
48
|
+
interface CheckoutMethodInfo {
|
|
49
|
+
method: "card" | "wallet" | "sympl" | "applepay";
|
|
50
|
+
label: string;
|
|
51
|
+
/** Customer surcharge applied to this method's checkout total, in basis points. */
|
|
52
|
+
feeBps?: number;
|
|
53
|
+
}
|
|
54
|
+
/** A verify target the dashboard can "Test" (key + label, optional integration field). */
|
|
55
|
+
interface ProviderVerifyTarget {
|
|
56
|
+
key: string;
|
|
57
|
+
label: string;
|
|
58
|
+
/**
|
|
59
|
+
* The non-secret config field holding this target's integration id (the box's
|
|
60
|
+
* primary field). Set ⇒ the dashboard renders the target as its own integration
|
|
61
|
+
* box; absent ⇒ an account-level probe shown in the credentials card.
|
|
62
|
+
*/
|
|
63
|
+
fieldKey?: string;
|
|
64
|
+
/** Additional non-secret config fields rendered inside the same integration box. */
|
|
65
|
+
extraFieldKeys?: string[];
|
|
66
|
+
/** Short helper text shown under the integration box. */
|
|
67
|
+
help?: string;
|
|
68
|
+
}
|
|
69
|
+
/** One verify target's live verdict. */
|
|
70
|
+
interface ProviderVerifyTargetResult {
|
|
71
|
+
/** The target key probed (matches a `PaymentProviderDefinition.verifyTargets` key). */
|
|
72
|
+
target: string;
|
|
73
|
+
configured: boolean;
|
|
74
|
+
/** The provider validated this target's config against its live API. */
|
|
75
|
+
valid: boolean;
|
|
76
|
+
/** HTTP status of the probe (0 = not configured / transport error). */
|
|
77
|
+
status: number;
|
|
78
|
+
detail: string;
|
|
79
|
+
/** Provider-specific extra detail (e.g. Paymob's gateway type). */
|
|
80
|
+
meta?: Record<string, string>;
|
|
81
|
+
/** Present only for a functional (money-moving) sub-test. */
|
|
82
|
+
functional?: {
|
|
83
|
+
ok: boolean;
|
|
84
|
+
status: number;
|
|
85
|
+
detail: string;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
interface ProviderVerifyResult {
|
|
89
|
+
provider: string;
|
|
90
|
+
currency: string;
|
|
91
|
+
targets: ProviderVerifyTargetResult[];
|
|
92
|
+
}
|
|
93
|
+
/** A credential set's non-secret surface (provider + currency + stored config). */
|
|
94
|
+
interface ProviderCredentialSummary {
|
|
95
|
+
provider: string;
|
|
96
|
+
currency: string;
|
|
97
|
+
config: Record<string, unknown>;
|
|
98
|
+
}
|
|
99
|
+
/** The editable view of one credential set — secret values are never returned. */
|
|
100
|
+
interface CredentialSet {
|
|
101
|
+
provider: string;
|
|
102
|
+
currency: string;
|
|
103
|
+
/** Stored non-secret field values, keyed by manifest field key (pre-fills the form). */
|
|
104
|
+
config: Record<string, unknown>;
|
|
105
|
+
/** Which secret fields currently have a value stored (the value is never returned). */
|
|
106
|
+
secretsSet: Record<string, boolean>;
|
|
107
|
+
updatedAt: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Create or rotate a credential set. `values` carries each field keyed by the
|
|
111
|
+
* provider definition's field key. On first create all required secrets are
|
|
112
|
+
* required; on update omit a secret to keep the stored one, send "" to clear a
|
|
113
|
+
* non-secret field, omit a field to leave it unchanged.
|
|
114
|
+
*/
|
|
115
|
+
interface UpsertCredentialsInput {
|
|
116
|
+
provider: string;
|
|
117
|
+
currency: string;
|
|
118
|
+
values: Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
/** The merchant's customer-facing business identity (seller block + email from-name). */
|
|
121
|
+
interface BusinessProfile {
|
|
122
|
+
displayName: string | null;
|
|
123
|
+
legalName: string | null;
|
|
124
|
+
address: string | null;
|
|
125
|
+
/** Contact phone (PRD-02). */
|
|
126
|
+
phone: string | null;
|
|
127
|
+
/** ISO-3166-1 alpha-2 country code, e.g. "EG" (PRD-02). */
|
|
128
|
+
country: string | null;
|
|
129
|
+
taxId: string | null;
|
|
130
|
+
supportEmail: string | null;
|
|
131
|
+
/** Logo image URL rendered on documents + emails; null = name-only branding. */
|
|
132
|
+
logoUrl: string | null;
|
|
133
|
+
/** Brand/accent color as `#RRGGBB` (PRD-11); null = billow's default accent. */
|
|
134
|
+
brandColor: string | null;
|
|
135
|
+
/** Org-default tax treatment (Phase E) — every taxable price inherits this. */
|
|
136
|
+
taxEnabled: boolean;
|
|
137
|
+
/** Default rate in basis points (1% = 100 bps), e.g. 1400 for Egypt's 14% VAT. */
|
|
138
|
+
taxRateBps: number;
|
|
139
|
+
taxBehavior: TaxBehavior;
|
|
140
|
+
/** What the tax is called on documents (e.g. "VAT"); null falls back to "Tax". */
|
|
141
|
+
taxLabel: string | null;
|
|
142
|
+
updatedAt: string;
|
|
143
|
+
}
|
|
144
|
+
/** Update a business profile; omit a field to leave it unchanged, send "" to clear it. */
|
|
145
|
+
interface UpdateBusinessProfileInput {
|
|
146
|
+
displayName?: string;
|
|
147
|
+
legalName?: string;
|
|
148
|
+
address?: string;
|
|
149
|
+
phone?: string;
|
|
150
|
+
country?: string;
|
|
151
|
+
taxId?: string;
|
|
152
|
+
supportEmail?: string;
|
|
153
|
+
logoUrl?: string;
|
|
154
|
+
/** `#RRGGBB` hex; empty string clears it (PRD-11). */
|
|
155
|
+
brandColor?: string;
|
|
156
|
+
taxEnabled?: boolean;
|
|
157
|
+
taxRateBps?: number;
|
|
158
|
+
taxBehavior?: TaxBehavior;
|
|
159
|
+
taxLabel?: string;
|
|
160
|
+
}
|
|
161
|
+
type IntegrationKind = "email" | "accounting";
|
|
162
|
+
type IntegrationTier = "official" | "community";
|
|
163
|
+
type ConfigFieldType = "text" | "password" | "email" | "url" | "number" | "percent" | "boolean" | "select";
|
|
164
|
+
interface ConfigFieldOption {
|
|
165
|
+
value: string;
|
|
166
|
+
label: string;
|
|
167
|
+
}
|
|
168
|
+
/** One field in an Integration's config manifest (the dashboard renders these). */
|
|
169
|
+
interface ConfigField {
|
|
170
|
+
key: string;
|
|
171
|
+
label: string;
|
|
172
|
+
type: ConfigFieldType;
|
|
173
|
+
/** Secret values are stored encrypted and never returned by a read. */
|
|
174
|
+
secret?: boolean;
|
|
175
|
+
required?: boolean;
|
|
176
|
+
placeholder?: string;
|
|
177
|
+
help?: string;
|
|
178
|
+
options?: ConfigFieldOption[];
|
|
179
|
+
default?: string | number | boolean;
|
|
180
|
+
}
|
|
181
|
+
/** A catalog Integration's declarative definition. */
|
|
182
|
+
interface IntegrationDefinition {
|
|
183
|
+
slug: string;
|
|
184
|
+
name: string;
|
|
185
|
+
kind: IntegrationKind;
|
|
186
|
+
tier: IntegrationTier;
|
|
187
|
+
summary: string;
|
|
188
|
+
description?: string;
|
|
189
|
+
fields: ConfigField[];
|
|
190
|
+
docsUrl?: string;
|
|
191
|
+
}
|
|
192
|
+
/** A catalog entry: the definition plus this tenant's install state. */
|
|
193
|
+
interface CatalogItem {
|
|
194
|
+
definition: IntegrationDefinition;
|
|
195
|
+
installed: boolean;
|
|
196
|
+
enabled: boolean;
|
|
197
|
+
/** Stored non-secret config values, for pre-filling the form. */
|
|
198
|
+
config: Record<string, unknown>;
|
|
199
|
+
/** Which secret fields have a value stored (the value itself is never returned). */
|
|
200
|
+
secretsSet: Record<string, boolean>;
|
|
201
|
+
/** Result of the last test/verify probe; null until tested (reset on reconfigure). */
|
|
202
|
+
lastTestStatus: "ok" | "error" | null;
|
|
203
|
+
/** Failure message from the last test, when it errored. */
|
|
204
|
+
lastTestError: string | null;
|
|
205
|
+
/** When the last test/verify probe ran (ISO), or null if never tested. */
|
|
206
|
+
lastTestedAt: string | null;
|
|
207
|
+
updatedAt: string | null;
|
|
208
|
+
}
|
|
209
|
+
/** A config field carries a secret value when explicitly marked or password-typed. */
|
|
210
|
+
declare function isSecretField(field: ConfigField): boolean;
|
|
211
|
+
|
|
212
|
+
/** Public SDK types for this domain. Re-exported by ../types.ts. */
|
|
213
|
+
|
|
214
|
+
/** The envelope every paginated list endpoint returns. */
|
|
215
|
+
interface Paginated<T> {
|
|
216
|
+
data: T[];
|
|
217
|
+
total: number;
|
|
218
|
+
limit: number;
|
|
219
|
+
offset: number;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The return type of every paginated `.list()`: BOTH a Promise for the first page AND
|
|
223
|
+
* async-iterable across ALL pages.
|
|
224
|
+
*
|
|
225
|
+
* - `await client.x.list(params)` → the first `Paginated<T>` page. `ListPromise<T>` is a
|
|
226
|
+
* structural subtype of the pre-pagination `Promise<Paginated<T>>`, so existing callers that
|
|
227
|
+
* `await` and read `.data` are unaffected.
|
|
228
|
+
* - `for await (const item of client.x.list(params))` → walks every page transparently.
|
|
229
|
+
* - `await client.x.list(params).listAll()` → collects every item into one array.
|
|
230
|
+
*
|
|
231
|
+
* Auto-pagination never reads `total` (it stops when a page comes back shorter than the page
|
|
232
|
+
* size), so it is correct under concurrent inserts/deletes; a list that grows at its head pages
|
|
233
|
+
* by cursor instead ({@link CursorListPromise}). The caller's {@link CallOptions} (`signal` /
|
|
234
|
+
* `timeoutMs`) apply to EVERY page
|
|
235
|
+
* fetch — an abort stops the walk mid-stream; `timeoutMs` is per page.
|
|
236
|
+
*
|
|
237
|
+
* A returned value is ONE walk: page 1 is cached on it (so `await` then `for await` on the same
|
|
238
|
+
* value fetch page 1 once), which means iterating the same value again later reuses that first
|
|
239
|
+
* page. For a fresh walk, call `.list()` again.
|
|
240
|
+
*/
|
|
241
|
+
interface ListPromise<T> extends Promise<Paginated<T>>, AsyncIterable<T> {
|
|
242
|
+
/** Page through the entire list and collect every item into one array. */
|
|
243
|
+
listAll(): Promise<T[]>;
|
|
244
|
+
}
|
|
245
|
+
interface ListParams {
|
|
246
|
+
limit?: number;
|
|
247
|
+
offset?: number;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The cursor-mode envelope, for a list whose rows keep arriving at the head (the credit ledger):
|
|
251
|
+
* pass `nextCursor` back as `cursor` for the next page; it is null on the last page.
|
|
252
|
+
*/
|
|
253
|
+
interface CursorPaginated<T> {
|
|
254
|
+
data: T[];
|
|
255
|
+
limit: number;
|
|
256
|
+
nextCursor: string | null;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The return type of a cursor-paginated `.list()`: like {@link ListPromise}, BOTH a Promise for
|
|
260
|
+
* the first page AND async-iterable across ALL pages (`for await`, or `.listAll()`). The walk
|
|
261
|
+
* follows `nextCursor` until it is null, so rows arriving at the head meanwhile never make it skip
|
|
262
|
+
* or repeat a row.
|
|
263
|
+
*/
|
|
264
|
+
interface CursorListPromise<T> extends Promise<CursorPaginated<T>>, AsyncIterable<T> {
|
|
265
|
+
/** Page through the entire list and collect every item into one array. */
|
|
266
|
+
listAll(): Promise<T[]>;
|
|
267
|
+
}
|
|
268
|
+
interface CursorListParams {
|
|
269
|
+
/** Page size: 1 to 100 (default 25); the server clamps a larger one. */
|
|
270
|
+
limit?: number;
|
|
271
|
+
/** A `nextCursor` to continue from; omit to start at the newest row. */
|
|
272
|
+
cursor?: string;
|
|
273
|
+
}
|
|
274
|
+
interface CustomerListItem {
|
|
275
|
+
id: string;
|
|
276
|
+
externalId: string;
|
|
277
|
+
name: string | null;
|
|
278
|
+
email: string | null;
|
|
279
|
+
phone: string | null;
|
|
280
|
+
subscriptionCount: number;
|
|
281
|
+
createdAt: string;
|
|
282
|
+
}
|
|
283
|
+
interface CustomerListParams extends ListParams {
|
|
284
|
+
/** Search across external id / email / name. */
|
|
285
|
+
q?: string;
|
|
286
|
+
}
|
|
287
|
+
interface PaymentMethod {
|
|
288
|
+
id: string;
|
|
289
|
+
brand: string | null;
|
|
290
|
+
last4: string | null;
|
|
291
|
+
expMonth: number | null;
|
|
292
|
+
expYear: number | null;
|
|
293
|
+
isDefault: boolean;
|
|
294
|
+
status: PaymentMethodStatus;
|
|
295
|
+
createdAt: string;
|
|
296
|
+
}
|
|
297
|
+
type EmailDeliveryStatus = "pending" | "sent" | "failed" | "skipped";
|
|
298
|
+
interface EmailDeliveryListItem {
|
|
299
|
+
id: string;
|
|
300
|
+
template: string;
|
|
301
|
+
recipient: string | null;
|
|
302
|
+
status: EmailDeliveryStatus | string;
|
|
303
|
+
attempts: number;
|
|
304
|
+
nextAttemptAt: string | null;
|
|
305
|
+
lastError: string | null;
|
|
306
|
+
sentAt: string | null;
|
|
307
|
+
createdAt: string;
|
|
308
|
+
}
|
|
309
|
+
interface EmailDeliveryListParams extends ListParams {
|
|
310
|
+
status?: EmailDeliveryStatus;
|
|
311
|
+
}
|
|
312
|
+
type OutboxEventStatus = "pending" | "delivered" | "failed";
|
|
313
|
+
interface OutboxEventListItem {
|
|
314
|
+
id: string;
|
|
315
|
+
type: string;
|
|
316
|
+
status: OutboxEventStatus;
|
|
317
|
+
attempts: number;
|
|
318
|
+
/** Failure reason from the most recent delivery attempt (null if none / delivered). */
|
|
319
|
+
error: string | null;
|
|
320
|
+
/** HTTP status of the most recent delivery attempt, if any. */
|
|
321
|
+
lastResponseStatus: number | null;
|
|
322
|
+
nextAttemptAt: string | null;
|
|
323
|
+
availableAt: string;
|
|
324
|
+
deliveredAt: string | null;
|
|
325
|
+
createdAt: string;
|
|
326
|
+
}
|
|
327
|
+
interface OutboxEventListParams extends ListParams {
|
|
328
|
+
status?: OutboxEventStatus;
|
|
329
|
+
}
|
|
330
|
+
type InboundWebhookOutcome = "signature_failed" | "shape_rejected" | "replayed" | "matched" | "unmatched" | "dispute_matched" | "dispute_unknown" | "dispute_deferred" | "accepted";
|
|
331
|
+
interface InboundWebhookListItem {
|
|
332
|
+
id: string;
|
|
333
|
+
provider: string;
|
|
334
|
+
outcome: InboundWebhookOutcome | string;
|
|
335
|
+
eventType: string | null;
|
|
336
|
+
providerEventId: string | null;
|
|
337
|
+
reference: string | null;
|
|
338
|
+
providerTransactionId: string | null;
|
|
339
|
+
/** The HTTP status billow returned to the provider (200 / 401 / 503). */
|
|
340
|
+
httpStatus: number;
|
|
341
|
+
detail: string | null;
|
|
342
|
+
createdAt: string;
|
|
343
|
+
}
|
|
344
|
+
interface InboundWebhookListParams extends ListParams {
|
|
345
|
+
outcome?: InboundWebhookOutcome;
|
|
346
|
+
}
|
|
347
|
+
interface CustomerUsage {
|
|
348
|
+
/** The metered feature's slug. */
|
|
349
|
+
feature: string;
|
|
350
|
+
/** Granted units this period; null = unlimited. */
|
|
351
|
+
allowance: number | null;
|
|
352
|
+
/** Gross units used this period (sum of positive events in the period). */
|
|
353
|
+
used: number;
|
|
354
|
+
/** Units topped up this period — gross credit-backs (negative events). */
|
|
355
|
+
added: number;
|
|
356
|
+
/** Remaining = allowance + added − used; null = unlimited. May be negative (overage). */
|
|
357
|
+
remaining: number | null;
|
|
358
|
+
/** Per-subscription counters in the order usage is consumed. */
|
|
359
|
+
details?: CustomerUsageDetail[];
|
|
360
|
+
}
|
|
361
|
+
interface CustomerUsageDetail {
|
|
362
|
+
subscriptionId: string;
|
|
363
|
+
productSlug: string;
|
|
364
|
+
productName: string;
|
|
365
|
+
status: SubscriptionStatus;
|
|
366
|
+
cancelAtPeriodEnd: boolean;
|
|
367
|
+
periodStart: string | null;
|
|
368
|
+
periodEnd: string | null;
|
|
369
|
+
allowance: number | null;
|
|
370
|
+
used: number;
|
|
371
|
+
remaining: number | null;
|
|
372
|
+
}
|
|
373
|
+
interface ChargeListItem {
|
|
374
|
+
id: string;
|
|
375
|
+
subtotal: number;
|
|
376
|
+
tax: number;
|
|
377
|
+
total: number;
|
|
378
|
+
taxRateBps: number | null;
|
|
379
|
+
taxBehavior: TaxBehavior | null;
|
|
380
|
+
/** Backward-compatible alias of `total`. */
|
|
381
|
+
amount: number;
|
|
382
|
+
currency: string;
|
|
383
|
+
status: ChargeStatus;
|
|
384
|
+
kind: "customer_present" | "mit";
|
|
385
|
+
customerExternalId: string;
|
|
386
|
+
customerEmail: string | null;
|
|
387
|
+
invoiceId: string | null;
|
|
388
|
+
specialReference: string;
|
|
389
|
+
providerTransactionId: string | null;
|
|
390
|
+
errorMessage: string | null;
|
|
391
|
+
/** Provider-reported dispute/chargeback (PRD-08), read-only. Null unless disputed. */
|
|
392
|
+
disputedAt: string | null;
|
|
393
|
+
disputeReason: string | null;
|
|
394
|
+
disputeState: "open" | "won" | "lost" | null;
|
|
395
|
+
providerDisputeId: string | null;
|
|
396
|
+
disputeAmount: number | null;
|
|
397
|
+
/** Set when this payment could not be applied to its invoice; null otherwise. */
|
|
398
|
+
unappliedReason: UnappliedPaymentReason | null;
|
|
399
|
+
createdAt: string;
|
|
400
|
+
}
|
|
401
|
+
interface ChargeListParams extends ListParams {
|
|
402
|
+
status?: ChargeStatus;
|
|
403
|
+
currency?: string;
|
|
404
|
+
/** Customer external id. */
|
|
405
|
+
customer?: string;
|
|
406
|
+
/** ISO-8601 lower bound (inclusive) on createdAt. */
|
|
407
|
+
from?: string;
|
|
408
|
+
/** ISO-8601 upper bound (inclusive) on createdAt. */
|
|
409
|
+
to?: string;
|
|
410
|
+
/** Filter by invoice membership: `false` = one-off charges only (receipts), `true` = invoice-backed only. */
|
|
411
|
+
hasInvoice?: boolean;
|
|
412
|
+
}
|
|
413
|
+
interface SubscriptionListItem {
|
|
414
|
+
id: string;
|
|
415
|
+
status: SubscriptionStatus;
|
|
416
|
+
customerExternalId: string;
|
|
417
|
+
productId: string;
|
|
418
|
+
productSlug: string;
|
|
419
|
+
productName: string;
|
|
420
|
+
/** The plan's metadata map (Stripe-style); `{}` when it carries none. */
|
|
421
|
+
productMetadata: Record<string, string>;
|
|
422
|
+
comp: boolean;
|
|
423
|
+
/** The subscription's billing currency (Phase F, ADR-0013). */
|
|
424
|
+
currency: string;
|
|
425
|
+
currentPeriodStart: string | null;
|
|
426
|
+
currentPeriodEnd: string | null;
|
|
427
|
+
trialEnd: string | null;
|
|
428
|
+
cancelAtPeriodEnd: boolean;
|
|
429
|
+
scheduledChange: ScheduledSubscriptionChange | null;
|
|
430
|
+
/** Renewals left before a limited-term subscription ends; null = open-ended. */
|
|
431
|
+
remainingCycles: number | null;
|
|
432
|
+
/** Failed-renewal retries run so far (PRD-06 dunning) — 0 until a renewal fails. */
|
|
433
|
+
dunningAttempts: number;
|
|
434
|
+
/** ISO-8601 time the next dunning retry is due; null when not in dunning (PRD-09). */
|
|
435
|
+
nextDunningAt: string | null;
|
|
436
|
+
createdAt: string;
|
|
437
|
+
}
|
|
438
|
+
interface ScheduledSubscriptionChange {
|
|
439
|
+
productVersionId: string;
|
|
440
|
+
productId: string;
|
|
441
|
+
productSlug: string;
|
|
442
|
+
productName: string;
|
|
443
|
+
effectiveAt: string | null;
|
|
444
|
+
}
|
|
445
|
+
interface SubscriptionListParams extends ListParams {
|
|
446
|
+
status?: SubscriptionStatus;
|
|
447
|
+
/** Customer external id. */
|
|
448
|
+
customer?: string;
|
|
449
|
+
}
|
|
450
|
+
/** A manually-maintained FX rate for cross-currency reporting (Phase F, ADR-0013). */
|
|
451
|
+
interface ExchangeRate {
|
|
452
|
+
baseCurrency: string;
|
|
453
|
+
quoteCurrency: string;
|
|
454
|
+
/** Quote per base, decimal (e.g. 0.020408 USD per EGP). */
|
|
455
|
+
rate: number;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* One transactional email template, merged with the project's overrides (PRD-10).
|
|
459
|
+
* The subject/message are `{{variable}}` templates over the server-defined
|
|
460
|
+
* `variables` allowlist; every template has a code default that renders when no
|
|
461
|
+
* override is set.
|
|
462
|
+
*/
|
|
463
|
+
interface EmailTemplateSetting {
|
|
464
|
+
/** Template key, e.g. "receipt", "payment_failed", "usage_cap". */
|
|
465
|
+
key: string;
|
|
466
|
+
label: string;
|
|
467
|
+
description: string;
|
|
468
|
+
/** The code-default subject (itself a `{{variable}}` template). */
|
|
469
|
+
defaultSubject: string;
|
|
470
|
+
/** The variables the subject/message may reference (without braces). */
|
|
471
|
+
variables: string[];
|
|
472
|
+
/** False for compliance-required templates (the receipt) — can't be disabled. */
|
|
473
|
+
canDisable: boolean;
|
|
474
|
+
/** Subject override, or null when the default is in effect. */
|
|
475
|
+
subject: string | null;
|
|
476
|
+
/** Custom message paragraph inserted after the greeting, or null. */
|
|
477
|
+
customMessage: string | null;
|
|
478
|
+
enabled: boolean;
|
|
479
|
+
}
|
|
480
|
+
interface UpdateEmailTemplateInput {
|
|
481
|
+
/** Subject override; null/"" resets to the default. Omit to keep. */
|
|
482
|
+
subject?: string | null;
|
|
483
|
+
/** Custom message paragraph; null/"" removes it. Omit to keep. */
|
|
484
|
+
customMessage?: string | null;
|
|
485
|
+
/** Omit to keep. Disabling a compliance-required template is rejected. */
|
|
486
|
+
enabled?: boolean;
|
|
487
|
+
}
|
|
488
|
+
interface CustomerOverview {
|
|
489
|
+
customer: Customer;
|
|
490
|
+
subscriptions: SubscriptionListItem[];
|
|
491
|
+
charges: ChargeListItem[];
|
|
492
|
+
paymentMethods: PaymentMethod[];
|
|
493
|
+
usage: CustomerUsage[];
|
|
494
|
+
}
|
|
495
|
+
interface CustomerSearchHit {
|
|
496
|
+
id: string;
|
|
497
|
+
externalId: string;
|
|
498
|
+
name: string | null;
|
|
499
|
+
email: string | null;
|
|
500
|
+
}
|
|
501
|
+
interface InvoiceSearchHit {
|
|
502
|
+
id: string;
|
|
503
|
+
number: string | null;
|
|
504
|
+
status: InvoiceStatus;
|
|
505
|
+
total: number;
|
|
506
|
+
currency: string;
|
|
507
|
+
customerExternalId: string;
|
|
508
|
+
}
|
|
509
|
+
interface SubscriptionSearchHit {
|
|
510
|
+
id: string;
|
|
511
|
+
status: SubscriptionStatus;
|
|
512
|
+
productName: string;
|
|
513
|
+
customerExternalId: string;
|
|
514
|
+
}
|
|
515
|
+
interface ChargeSearchHit {
|
|
516
|
+
id: string;
|
|
517
|
+
amount: number;
|
|
518
|
+
currency: string;
|
|
519
|
+
status: ChargeStatus;
|
|
520
|
+
/** The charge's idempotency reference (`special_reference`). */
|
|
521
|
+
reference: string;
|
|
522
|
+
customerExternalId: string;
|
|
523
|
+
}
|
|
524
|
+
interface SearchResults {
|
|
525
|
+
customers: CustomerSearchHit[];
|
|
526
|
+
invoices: InvoiceSearchHit[];
|
|
527
|
+
subscriptions: SubscriptionSearchHit[];
|
|
528
|
+
charges: ChargeSearchHit[];
|
|
529
|
+
}
|
|
530
|
+
interface Invoice {
|
|
531
|
+
id: string;
|
|
532
|
+
status: InvoiceStatus;
|
|
533
|
+
customerId: string;
|
|
534
|
+
subscriptionId: string | null;
|
|
535
|
+
subtotal: number;
|
|
536
|
+
discountTotal: number;
|
|
537
|
+
usageTotal: number;
|
|
538
|
+
/** Tax/VAT amount (minor units); also recorded against the tax ids below. */
|
|
539
|
+
taxTotal: number;
|
|
540
|
+
/** Tax rate in basis points snapshotted at issue; null = untaxed. */
|
|
541
|
+
taxRateBps: number | null;
|
|
542
|
+
/** The tax treatment snapshotted at issue; null = untaxed. Inclusive tax is already in `total`. */
|
|
543
|
+
taxBehavior: TaxBehavior | null;
|
|
544
|
+
/** The customer's tax id snapshotted at issue (null if none). */
|
|
545
|
+
customerTaxId: string | null;
|
|
546
|
+
/** The merchant's tax registration snapshotted at issue (null if none). */
|
|
547
|
+
merchantTaxId: string | null;
|
|
548
|
+
total: number;
|
|
549
|
+
currency: string;
|
|
550
|
+
/**
|
|
551
|
+
* Cross-currency reporting snapshot (Phase F, ADR-0013). `reportingCurrency` is the
|
|
552
|
+
* org's reporting currency at issue; `fxRate` converts this invoice's `currency`
|
|
553
|
+
* into it (1.0 when the same). Both null = no reporting currency configured; a
|
|
554
|
+
* non-null `reportingCurrency` with a null `fxRate` = no rate was on file (this
|
|
555
|
+
* invoice can't be rolled up).
|
|
556
|
+
*/
|
|
557
|
+
reportingCurrency: string | null;
|
|
558
|
+
fxRate: number | null;
|
|
559
|
+
periodStart: string | null;
|
|
560
|
+
periodEnd: string | null;
|
|
561
|
+
createdAt: string;
|
|
562
|
+
}
|
|
563
|
+
interface InvoiceLineItem {
|
|
564
|
+
id: string;
|
|
565
|
+
invoiceId: string;
|
|
566
|
+
type: string;
|
|
567
|
+
description: string | null;
|
|
568
|
+
amount: number;
|
|
569
|
+
quantity: number;
|
|
570
|
+
currency: string;
|
|
571
|
+
}
|
|
572
|
+
interface InvoiceListItem {
|
|
573
|
+
id: string;
|
|
574
|
+
/** Sequential invoice number, snapshotted when paid; null if not yet assigned. */
|
|
575
|
+
number: string | null;
|
|
576
|
+
status: InvoiceStatus;
|
|
577
|
+
total: number;
|
|
578
|
+
currency: string;
|
|
579
|
+
customerExternalId: string;
|
|
580
|
+
subscriptionId: string | null;
|
|
581
|
+
/** What the invoice is for — the plan name (subscriptions) or first line item. */
|
|
582
|
+
reason: string | null;
|
|
583
|
+
periodStart: string | null;
|
|
584
|
+
periodEnd: string | null;
|
|
585
|
+
createdAt: string;
|
|
586
|
+
/** When the invoice was paid (null if unpaid). */
|
|
587
|
+
paidAt: string | null;
|
|
588
|
+
/** The settling charge's receipt number (paid invoices only); null otherwise. */
|
|
589
|
+
receiptNumber: string | null;
|
|
590
|
+
}
|
|
591
|
+
interface InvoiceListParams extends ListParams {
|
|
592
|
+
status?: InvoiceStatus;
|
|
593
|
+
/** Customer external id. */
|
|
594
|
+
customer?: string;
|
|
595
|
+
from?: string;
|
|
596
|
+
to?: string;
|
|
597
|
+
}
|
|
598
|
+
interface InvoiceDetail {
|
|
599
|
+
invoice: Invoice;
|
|
600
|
+
lineItems: InvoiceLineItem[];
|
|
601
|
+
}
|
|
602
|
+
/** How an offline payment was collected (ADR-0026). `other` is the escape hatch. */
|
|
603
|
+
type ExternalPaymentMethod = "bank_transfer" | "cash" | "cheque" | "other";
|
|
604
|
+
/**
|
|
605
|
+
* Record that an open invoice was paid outside the gateway. `amount` must equal the invoice
|
|
606
|
+
* total (full settlement only); `reference` carries the operator's detail (transfer id, etc.).
|
|
607
|
+
*/
|
|
608
|
+
interface RecordExternalPaymentInput {
|
|
609
|
+
amount: number;
|
|
610
|
+
method: ExternalPaymentMethod;
|
|
611
|
+
reference?: string;
|
|
612
|
+
/** ISO-8601 time the payment was received; defaults to now. */
|
|
613
|
+
paidAt?: string;
|
|
614
|
+
}
|
|
615
|
+
/** The settling charge recorded for an external payment. */
|
|
616
|
+
interface ExternalPaymentResult {
|
|
617
|
+
id: string;
|
|
618
|
+
invoiceId: string | null;
|
|
619
|
+
amount: number;
|
|
620
|
+
currency: string;
|
|
621
|
+
status: ChargeStatus;
|
|
622
|
+
receiptNumber: string | null;
|
|
623
|
+
method: ExternalPaymentMethod | null;
|
|
624
|
+
reference: string | null;
|
|
625
|
+
paidAt: string | null;
|
|
626
|
+
}
|
|
627
|
+
interface MetricsOverview {
|
|
628
|
+
currency: string;
|
|
629
|
+
from: string;
|
|
630
|
+
to: string;
|
|
631
|
+
/** Monthly recurring revenue (minor units). */
|
|
632
|
+
mrr: number;
|
|
633
|
+
/** Annual recurring revenue (minor units) — `mrr × 12`. */
|
|
634
|
+
arr: number;
|
|
635
|
+
/** Cohort subscription churn over the window (0..1); null if none were active at its start. */
|
|
636
|
+
churnRate: number | null;
|
|
637
|
+
activeSubscriptions: number;
|
|
638
|
+
pastDueSubscriptions: number;
|
|
639
|
+
revenue: number;
|
|
640
|
+
newCustomers: number;
|
|
641
|
+
newSubscriptions: number;
|
|
642
|
+
canceledSubscriptions: number;
|
|
643
|
+
failedCharges: number;
|
|
644
|
+
/** Succeeded / (succeeded + failed); 0..1, or null if no attempts in the window. */
|
|
645
|
+
successRate: number | null;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* KPIs rolled up into the org's reporting currency across all billing currencies
|
|
649
|
+
* (Phase H, ADR-0013). `metrics.rollup` returns `null` when no reporting currency
|
|
650
|
+
* is configured. Money figures are in `reportingCurrency` (minor units); MRR/ARR
|
|
651
|
+
* convert at the current stored rate, revenue at each invoice's FX snapshot.
|
|
652
|
+
*/
|
|
653
|
+
interface MetricsRollup {
|
|
654
|
+
reportingCurrency: string;
|
|
655
|
+
from: string;
|
|
656
|
+
to: string;
|
|
657
|
+
mrr: number;
|
|
658
|
+
arr: number;
|
|
659
|
+
revenue: number;
|
|
660
|
+
activeSubscriptions: number;
|
|
661
|
+
pastDueSubscriptions: number;
|
|
662
|
+
newCustomers: number;
|
|
663
|
+
newSubscriptions: number;
|
|
664
|
+
canceledSubscriptions: number;
|
|
665
|
+
churnRate: number | null;
|
|
666
|
+
failedCharges: number;
|
|
667
|
+
successRate: number | null;
|
|
668
|
+
/** Currencies excluded from mrr/revenue for want of a rate (surfaced, never guessed). */
|
|
669
|
+
unconvertibleCurrencies: string[];
|
|
670
|
+
}
|
|
671
|
+
type TimeseriesMetric = "revenue" | "mrr" | "new_subscriptions" | "canceled_subscriptions" | "success_rate";
|
|
672
|
+
type TimeseriesInterval = "day" | "week" | "month";
|
|
673
|
+
interface TimeseriesPoint {
|
|
674
|
+
bucket: string;
|
|
675
|
+
value: number;
|
|
676
|
+
}
|
|
677
|
+
interface TimeseriesResult {
|
|
678
|
+
metric: TimeseriesMetric;
|
|
679
|
+
currency: string;
|
|
680
|
+
interval: TimeseriesInterval;
|
|
681
|
+
points: TimeseriesPoint[];
|
|
682
|
+
}
|
|
683
|
+
interface MetricsParams {
|
|
684
|
+
currency?: string;
|
|
685
|
+
from?: string;
|
|
686
|
+
to?: string;
|
|
687
|
+
}
|
|
688
|
+
interface TimeseriesParams extends MetricsParams {
|
|
689
|
+
metric?: TimeseriesMetric;
|
|
690
|
+
interval?: TimeseriesInterval;
|
|
691
|
+
}
|
|
692
|
+
interface Whoami {
|
|
693
|
+
/** The apex account that owns the Project (ADR-0020). */
|
|
694
|
+
organizationId: string;
|
|
695
|
+
organizationName: string | null;
|
|
696
|
+
organizationSlug: string | null;
|
|
697
|
+
/** The billing workspace the API key scopes to — what every resource belongs to. */
|
|
698
|
+
projectId: string;
|
|
699
|
+
projectName: string | null;
|
|
700
|
+
projectSlug: string | null;
|
|
701
|
+
environment: "sandbox" | "live";
|
|
702
|
+
apiKeyType: string;
|
|
703
|
+
/** Currencies configured for this Project (payment credential sets). */
|
|
704
|
+
currencies: string[];
|
|
705
|
+
defaultCurrency: string;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/** What surface a portal session lands the Customer on. */
|
|
709
|
+
type PortalSessionFlow = "portal" | "checkout";
|
|
710
|
+
interface CreatePortalSessionInput {
|
|
711
|
+
/** The Customer's developer-supplied id. */
|
|
712
|
+
customerId: string;
|
|
713
|
+
/** Which surface to land on; defaults to the self-serve portal. */
|
|
714
|
+
flow?: PortalSessionFlow;
|
|
715
|
+
/** Product slug to subscribe to — required when `flow` is `checkout`. */
|
|
716
|
+
productId?: string;
|
|
717
|
+
/** Where the surface returns the Customer when they finish or exit. */
|
|
718
|
+
returnUrl?: string;
|
|
719
|
+
}
|
|
720
|
+
/** The minted portal session: redirect the Customer to `url` (it carries the bearer). */
|
|
721
|
+
interface PortalSession {
|
|
722
|
+
id: string;
|
|
723
|
+
url: string;
|
|
724
|
+
flow: PortalSessionFlow;
|
|
725
|
+
/** ISO-8601 expiry — the session (and its URL) stop working after this. */
|
|
726
|
+
expiresAt: string;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* The portal shell: the session's flow + return URL, the merchant's
|
|
730
|
+
* customer-facing brand, and the Customer's identity. The lightweight payload a
|
|
731
|
+
* hosting app frames every page with (no subscription/usage load), and the
|
|
732
|
+
* validate-and-route check at login.
|
|
733
|
+
*/
|
|
734
|
+
interface PortalSessionInfo {
|
|
735
|
+
flow: PortalSessionFlow;
|
|
736
|
+
returnUrl: string | null;
|
|
737
|
+
/** The merchant's customer-facing brand (name + support + logo + accent) and the
|
|
738
|
+
* white-label mark gate (PRD-11). */
|
|
739
|
+
business: {
|
|
740
|
+
name: string;
|
|
741
|
+
supportEmail: string | null;
|
|
742
|
+
logoUrl: string | null;
|
|
743
|
+
brandColor: string | null;
|
|
744
|
+
showBillowMark: boolean;
|
|
745
|
+
};
|
|
746
|
+
/** The session's Customer (the only identity the portal shell needs). */
|
|
747
|
+
customer: {
|
|
748
|
+
externalId: string;
|
|
749
|
+
name: string | null;
|
|
750
|
+
email: string | null;
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
/** The self-serve home payload returned to the portal app (`BillowPortal.me`). */
|
|
754
|
+
interface PortalView {
|
|
755
|
+
customer: {
|
|
756
|
+
id: string;
|
|
757
|
+
externalId: string;
|
|
758
|
+
name: string | null;
|
|
759
|
+
email: string | null;
|
|
760
|
+
};
|
|
761
|
+
flow: PortalSessionFlow;
|
|
762
|
+
returnUrl: string | null;
|
|
763
|
+
subscriptions: SubscriptionListItem[];
|
|
764
|
+
usage: CustomerUsage[];
|
|
765
|
+
paymentMethods: SavedPaymentMethod[];
|
|
766
|
+
}
|
|
767
|
+
/** The subscription's state after a portal cancel (scheduled at period end). */
|
|
768
|
+
interface PortalSubscriptionStatus {
|
|
769
|
+
id: string;
|
|
770
|
+
status: string;
|
|
771
|
+
cancelAtPeriodEnd: boolean;
|
|
772
|
+
currentPeriodEnd: string | null;
|
|
773
|
+
scheduledChange: ScheduledSubscriptionChange | null;
|
|
774
|
+
}
|
|
775
|
+
/** The outcome of a portal-driven plan change (PRD-15). */
|
|
776
|
+
interface PortalPlanChange {
|
|
777
|
+
/** upgrade = prorated + charged now; downgrade = scheduled for period end; noop = same plan. */
|
|
778
|
+
kind: "upgrade" | "downgrade" | "noop";
|
|
779
|
+
subscription: PortalSubscriptionStatus;
|
|
780
|
+
/** Upgrade only: the proration invoice raised for the prorated delta, when non-zero. */
|
|
781
|
+
prorationInvoiceId?: string;
|
|
782
|
+
/** Upgrade only: the proration charge's status (`succeeded`/`failed`/`processing`/`pending`) —
|
|
783
|
+
* present when an immediate charge was raised, so a client can surface an unresolved payment. */
|
|
784
|
+
chargeStatus?: string;
|
|
785
|
+
}
|
|
786
|
+
/** The checkout URL to redirect the Customer to for a card update (null if none). */
|
|
787
|
+
interface PortalCardSetupResult {
|
|
788
|
+
checkoutUrl: string | null;
|
|
789
|
+
}
|
|
790
|
+
/** The plan a `checkout` portal session is confirming (product + its base price). */
|
|
791
|
+
interface PortalCheckout {
|
|
792
|
+
product: {
|
|
793
|
+
slug: string;
|
|
794
|
+
name: string;
|
|
795
|
+
};
|
|
796
|
+
price: {
|
|
797
|
+
amount: number;
|
|
798
|
+
currency: string;
|
|
799
|
+
interval: string | null;
|
|
800
|
+
} | null;
|
|
801
|
+
returnUrl: string | null;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
type ExportJsonValue = string | number | boolean | null | ExportJsonValue[] | {
|
|
805
|
+
[key: string]: ExportJsonValue;
|
|
806
|
+
};
|
|
807
|
+
interface CustomerDataExport {
|
|
808
|
+
generatedAt: string;
|
|
809
|
+
customer: {
|
|
810
|
+
id: string;
|
|
811
|
+
externalId: string;
|
|
812
|
+
name: string | null;
|
|
813
|
+
email: string | null;
|
|
814
|
+
phone: string | null;
|
|
815
|
+
taxId: string | null;
|
|
816
|
+
createdAt: string;
|
|
817
|
+
updatedAt: string;
|
|
818
|
+
};
|
|
819
|
+
paymentMethods: Array<{
|
|
820
|
+
id: string;
|
|
821
|
+
provider: string;
|
|
822
|
+
brand: string | null;
|
|
823
|
+
last4: string | null;
|
|
824
|
+
expMonth: number | null;
|
|
825
|
+
expYear: number | null;
|
|
826
|
+
isDefault: boolean;
|
|
827
|
+
status: PaymentMethodStatus;
|
|
828
|
+
createdAt: string;
|
|
829
|
+
}>;
|
|
830
|
+
subscriptions: Array<{
|
|
831
|
+
id: string;
|
|
832
|
+
customerId: string;
|
|
833
|
+
productVersionId: string;
|
|
834
|
+
currency: string;
|
|
835
|
+
status: string;
|
|
836
|
+
currentPeriodStart: string | null;
|
|
837
|
+
currentPeriodEnd: string | null;
|
|
838
|
+
trialEnd: string | null;
|
|
839
|
+
cancelAtPeriodEnd: boolean;
|
|
840
|
+
canceledAt: string | null;
|
|
841
|
+
scheduledChange: ExportJsonValue | null;
|
|
842
|
+
createdAt: string;
|
|
843
|
+
updatedAt: string;
|
|
844
|
+
}>;
|
|
845
|
+
subscriptionItems: Array<{
|
|
846
|
+
id: string;
|
|
847
|
+
subscriptionId: string;
|
|
848
|
+
priceId: string;
|
|
849
|
+
quantity: number;
|
|
850
|
+
createdAt: string;
|
|
851
|
+
updatedAt: string;
|
|
852
|
+
}>;
|
|
853
|
+
discounts: Array<{
|
|
854
|
+
id: string;
|
|
855
|
+
subscriptionId: string;
|
|
856
|
+
couponId: string;
|
|
857
|
+
cyclesRemaining: number | null;
|
|
858
|
+
createdAt: string;
|
|
859
|
+
updatedAt: string;
|
|
860
|
+
}>;
|
|
861
|
+
invoices: Array<{
|
|
862
|
+
id: string;
|
|
863
|
+
customerId: string;
|
|
864
|
+
subscriptionId: string | null;
|
|
865
|
+
number: string | null;
|
|
866
|
+
status: InvoiceStatus;
|
|
867
|
+
subtotal: number;
|
|
868
|
+
discountTotal: number;
|
|
869
|
+
usageTotal: number;
|
|
870
|
+
taxTotal: number;
|
|
871
|
+
total: number;
|
|
872
|
+
currency: string;
|
|
873
|
+
periodStart: string | null;
|
|
874
|
+
periodEnd: string | null;
|
|
875
|
+
createdAt: string;
|
|
876
|
+
updatedAt: string;
|
|
877
|
+
}>;
|
|
878
|
+
invoiceLineItems: Array<{
|
|
879
|
+
id: string;
|
|
880
|
+
invoiceId: string;
|
|
881
|
+
type: string;
|
|
882
|
+
description: string | null;
|
|
883
|
+
amount: number;
|
|
884
|
+
quantity: number;
|
|
885
|
+
currency: string;
|
|
886
|
+
createdAt: string;
|
|
887
|
+
updatedAt: string;
|
|
888
|
+
}>;
|
|
889
|
+
charges: Array<{
|
|
890
|
+
id: string;
|
|
891
|
+
invoiceId: string | null;
|
|
892
|
+
paymentMethodId: string | null;
|
|
893
|
+
kind: string;
|
|
894
|
+
subtotal: number;
|
|
895
|
+
tax: number;
|
|
896
|
+
amount: number;
|
|
897
|
+
currency: string;
|
|
898
|
+
provider: string;
|
|
899
|
+
receiptNumber: string | null;
|
|
900
|
+
status: ChargeStatus;
|
|
901
|
+
disputedAt: string | null;
|
|
902
|
+
disputeReason: string | null;
|
|
903
|
+
disputeAmount: number | null;
|
|
904
|
+
createdAt: string;
|
|
905
|
+
updatedAt: string;
|
|
906
|
+
}>;
|
|
907
|
+
refunds: Array<{
|
|
908
|
+
id: string;
|
|
909
|
+
chargeId: string;
|
|
910
|
+
amount: number;
|
|
911
|
+
subtotal: number;
|
|
912
|
+
tax: number;
|
|
913
|
+
currency: string;
|
|
914
|
+
status: RefundStatus;
|
|
915
|
+
providerRefundId: string | null;
|
|
916
|
+
creditNoteNumber: string | null;
|
|
917
|
+
createdAt: string;
|
|
918
|
+
updatedAt: string;
|
|
919
|
+
}>;
|
|
920
|
+
usageEvents: Array<{
|
|
921
|
+
id: string;
|
|
922
|
+
featureId: string;
|
|
923
|
+
value: number;
|
|
924
|
+
properties: ExportJsonValue;
|
|
925
|
+
occurredAt: string;
|
|
926
|
+
createdAt: string;
|
|
927
|
+
}>;
|
|
928
|
+
/** The customer's prepaid credits. Every credit quantity is a decimal string of microcredits. */
|
|
929
|
+
credits: CustomerCreditsExport;
|
|
930
|
+
}
|
|
931
|
+
/** A customer's prepaid credits in the data export; empty when they never had a credit account. */
|
|
932
|
+
interface CustomerCreditsExport {
|
|
933
|
+
account: {
|
|
934
|
+
id: string;
|
|
935
|
+
status: "active" | "frozen" | "closed";
|
|
936
|
+
/** The grants' unheld credits, as the ledger has them. */
|
|
937
|
+
available: string;
|
|
938
|
+
/** What can be spent now: `available` less credits already past their expiry. */
|
|
939
|
+
spendable: string;
|
|
940
|
+
held: string;
|
|
941
|
+
/** The threshold level the account's last balance change left it at. */
|
|
942
|
+
thresholdLevel: CreditThresholdLevel;
|
|
943
|
+
createdAt: string;
|
|
944
|
+
updatedAt: string;
|
|
945
|
+
} | null;
|
|
946
|
+
grants: CreditGrant[];
|
|
947
|
+
reservations: Array<{
|
|
948
|
+
id: string;
|
|
949
|
+
/** The customer's external id. */
|
|
950
|
+
customerId: string;
|
|
951
|
+
operationKey: string;
|
|
952
|
+
category: string;
|
|
953
|
+
amount: string;
|
|
954
|
+
consumed: string;
|
|
955
|
+
status: "held" | "protected" | "committed" | "released" | "expired";
|
|
956
|
+
expiresAt: string;
|
|
957
|
+
protectedAt: string | null;
|
|
958
|
+
settledAt: string | null;
|
|
959
|
+
/** The commit's `consume` ledger transaction. */
|
|
960
|
+
consumptionId: string | null;
|
|
961
|
+
metadata: Record<string, string> | null;
|
|
962
|
+
createdAt: string;
|
|
963
|
+
}>;
|
|
964
|
+
/** Every credit top-up, as it now stands. */
|
|
965
|
+
topUps: CreditTopUp[];
|
|
966
|
+
/** Every consumption reversal, with your own reason and metadata (cleared on erasure). */
|
|
967
|
+
reversals: Array<{
|
|
968
|
+
id: string;
|
|
969
|
+
/** The customer's external id. */
|
|
970
|
+
customerId: string;
|
|
971
|
+
/** The consumption reversed: its commit's `consume` ledger transaction. */
|
|
972
|
+
consumptionId: string;
|
|
973
|
+
/** The `reverse` ledger transaction. */
|
|
974
|
+
transactionId: string;
|
|
975
|
+
amount: string;
|
|
976
|
+
/** Of `amount`, what came back to an expired grant and expired again at once. */
|
|
977
|
+
forfeited: string;
|
|
978
|
+
reason: string | null;
|
|
979
|
+
metadata: Record<string, string> | null;
|
|
980
|
+
createdAt: string;
|
|
981
|
+
}>;
|
|
982
|
+
/** Every ledger transaction, in the order it was written, with its postings. */
|
|
983
|
+
ledger: Array<{
|
|
984
|
+
id: string;
|
|
985
|
+
type: "grant" | "hold" | "release" | "consume" | "expire" | "reverse" | "revoke" | "adjust";
|
|
986
|
+
grantId: string | null;
|
|
987
|
+
reservationId: string | null;
|
|
988
|
+
topUpId: string | null;
|
|
989
|
+
consumptionId: string | null;
|
|
990
|
+
reason: string | null;
|
|
991
|
+
availableAfter: string;
|
|
992
|
+
heldAfter: string;
|
|
993
|
+
createdAt: string;
|
|
994
|
+
postings: Array<{
|
|
995
|
+
grantId: string | null;
|
|
996
|
+
bucket: "available" | "held" | "issued" | "consumed" | "expired";
|
|
997
|
+
amount: string;
|
|
998
|
+
}>;
|
|
999
|
+
consumptionItems: Array<{
|
|
1000
|
+
action: string;
|
|
1001
|
+
category: string;
|
|
1002
|
+
units: string;
|
|
1003
|
+
amount: string;
|
|
1004
|
+
rateCardVersion: number | null;
|
|
1005
|
+
dimensions: ExportJsonValue;
|
|
1006
|
+
}>;
|
|
1007
|
+
}>;
|
|
1008
|
+
}
|
|
1009
|
+
interface CustomerAnonymizationResult {
|
|
1010
|
+
id: string;
|
|
1011
|
+
anonymizedAt: string;
|
|
1012
|
+
retainedRecords: string[];
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/** Public SDK types for refunds and their review. Re-exported by ../types.ts. */
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Why a refund waits for an Operator:
|
|
1019
|
+
* - `unconfirmed`: the provider never confirmed it within its reconcile attempts;
|
|
1020
|
+
* - `unconfirmable_without_provider_id`: the provider's answer to the refund request was lost
|
|
1021
|
+
* before it returned a refund id, and the provider can find a refund only by that id (Paymob),
|
|
1022
|
+
* so nothing Billow can ask it would confirm this request;
|
|
1023
|
+
* - `provider_conflict`: the provider answered against this refund's recorded outcome;
|
|
1024
|
+
* - `conflict_on_charge`: another refund of the charge has an unresolved provider conflict.
|
|
1025
|
+
*/
|
|
1026
|
+
type RefundReviewReason = "unconfirmed" | "unconfirmable_without_provider_id" | "provider_conflict" | "conflict_on_charge";
|
|
1027
|
+
interface Refund {
|
|
1028
|
+
id: string;
|
|
1029
|
+
chargeId: string;
|
|
1030
|
+
amount: number;
|
|
1031
|
+
subtotal: number;
|
|
1032
|
+
tax: number;
|
|
1033
|
+
currency: string;
|
|
1034
|
+
/**
|
|
1035
|
+
* `pending` while the provider is settling it or its answer was lost (the amount stays
|
|
1036
|
+
* reserved and further refunds of the charge are refused until it settles).
|
|
1037
|
+
*/
|
|
1038
|
+
status: RefundStatus;
|
|
1039
|
+
/**
|
|
1040
|
+
* Billow cannot settle this refund on its own (`reviewReason` says why): check the provider
|
|
1041
|
+
* dashboard, then `charges.recheckRefund` or `charges.resolveRefund` it.
|
|
1042
|
+
*/
|
|
1043
|
+
needsReview: boolean;
|
|
1044
|
+
/** Why it needs (or needed) review - see `RefundReviewReason`. */
|
|
1045
|
+
reviewReason: RefundReviewReason | null;
|
|
1046
|
+
providerRefundId: string | null;
|
|
1047
|
+
creditNoteNumber: string | null;
|
|
1048
|
+
/**
|
|
1049
|
+
* Set while the provider's own answer, which arrived after the refund was already settled the
|
|
1050
|
+
* other way (e.g. `succeeded` for a refund resolved as not refunded), is unresolved: the money
|
|
1051
|
+
* moved differently from what `status` says. The charge is held (no new refunds) until it is
|
|
1052
|
+
* resolved as refunded with `charges.resolveRefund`, which clears it.
|
|
1053
|
+
*/
|
|
1054
|
+
providerConflictStatus: RefundStatus | null;
|
|
1055
|
+
/** When that contrary answer arrived (kept after the conflict is resolved). */
|
|
1056
|
+
providerConflictAt: string | null;
|
|
1057
|
+
/** The note recorded when an Operator resolved the refund by hand, else null. */
|
|
1058
|
+
resolutionNote: string | null;
|
|
1059
|
+
/** The API key that recorded the manual resolution, else null. */
|
|
1060
|
+
resolvedBy: string | null;
|
|
1061
|
+
resolvedAt: string | null;
|
|
1062
|
+
createdAt: string;
|
|
1063
|
+
}
|
|
1064
|
+
/** A refund of a succeeded charge. */
|
|
1065
|
+
interface RefundChargeInput {
|
|
1066
|
+
/** Minor units to refund (a partial); omit to refund the charge's whole remaining balance. */
|
|
1067
|
+
amount?: number;
|
|
1068
|
+
}
|
|
1069
|
+
/** What `charges.refund` answers: the refund its idempotency key stands for. */
|
|
1070
|
+
interface RefundRequestResult extends Refund {
|
|
1071
|
+
/**
|
|
1072
|
+
* `true` when the idempotency key was already used: this is the refund that earlier request
|
|
1073
|
+
* made, as it stands now, and nothing new was refunded. `false` when this call made it.
|
|
1074
|
+
*/
|
|
1075
|
+
replayed: boolean;
|
|
1076
|
+
}
|
|
1077
|
+
/** The outcome an Operator verified in the provider dashboard for a refund awaiting review. */
|
|
1078
|
+
interface ResolveRefundInput {
|
|
1079
|
+
/** `succeeded`: the provider refunded it. `failed`: no refund exists at the provider. */
|
|
1080
|
+
outcome: "succeeded" | "failed";
|
|
1081
|
+
/** Required. What was checked, e.g. the provider's refund reference. */
|
|
1082
|
+
note: string;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/** Public SDK types for this domain. Re-exported by ../types.ts. */
|
|
1086
|
+
|
|
1087
|
+
/** A registered developer webhook endpoint. The signing secret is never listed. */
|
|
1088
|
+
interface WebhookEndpoint {
|
|
1089
|
+
id: string;
|
|
1090
|
+
url: string;
|
|
1091
|
+
enabled: boolean;
|
|
1092
|
+
/** Subscribed event types, or `["*"]` for all. */
|
|
1093
|
+
eventTypes: string[];
|
|
1094
|
+
/**
|
|
1095
|
+
* When billow auto-disabled this endpoint after repeated delivery failures, else
|
|
1096
|
+
* null. Re-enabling it (set `enabled: true`) clears this and resumes delivery.
|
|
1097
|
+
*/
|
|
1098
|
+
disabledAt: string | null;
|
|
1099
|
+
/** Human-readable reason it was auto-disabled, else null. */
|
|
1100
|
+
disabledReason: string | null;
|
|
1101
|
+
createdAt: string;
|
|
1102
|
+
updatedAt: string;
|
|
1103
|
+
}
|
|
1104
|
+
/** Returned once at create/rotate — carries the plaintext signing secret. */
|
|
1105
|
+
interface WebhookEndpointWithSecret extends WebhookEndpoint {
|
|
1106
|
+
/** The HMAC signing secret — shown exactly once. Store it now; it is never listed again. */
|
|
1107
|
+
secret: string;
|
|
1108
|
+
}
|
|
1109
|
+
interface CreateWebhookEndpointInput {
|
|
1110
|
+
url: string;
|
|
1111
|
+
/** Defaults to all events (`["*"]`). */
|
|
1112
|
+
eventTypes?: string[];
|
|
1113
|
+
enabled?: boolean;
|
|
1114
|
+
}
|
|
1115
|
+
interface UpdateWebhookEndpointInput {
|
|
1116
|
+
url?: string;
|
|
1117
|
+
eventTypes?: string[];
|
|
1118
|
+
enabled?: boolean;
|
|
1119
|
+
}
|
|
1120
|
+
/** One recorded delivery attempt of an event to an endpoint. */
|
|
1121
|
+
interface WebhookDelivery {
|
|
1122
|
+
id: string;
|
|
1123
|
+
/** The event envelope id this attempt delivered. */
|
|
1124
|
+
eventId: string;
|
|
1125
|
+
/** "delivered" once a 2xx was received, else "failed". */
|
|
1126
|
+
status: WebhookDeliveryStatus;
|
|
1127
|
+
attempts: number;
|
|
1128
|
+
/** HTTP status of the last attempt, or null if the request never completed. */
|
|
1129
|
+
lastResponseStatus: number | null;
|
|
1130
|
+
lastError: string | null;
|
|
1131
|
+
deliveredAt: string | null;
|
|
1132
|
+
createdAt: string;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
declare class BillowApiError extends Error {
|
|
1136
|
+
readonly status: number;
|
|
1137
|
+
/**
|
|
1138
|
+
* A known {@link BillowErrorCode} (widened to `string` so a newer server's code still type-checks),
|
|
1139
|
+
* or one the SDK raises itself: `invalid_response` for a success (2xx other than 204) whose body
|
|
1140
|
+
* was empty or could not be read or parsed. The request reached billow and was answered, but what
|
|
1141
|
+
* it answered is unknown - for a write, treat the outcome as UNKNOWN (retry it under the same
|
|
1142
|
+
* idempotency key), never as done or as refused.
|
|
1143
|
+
*/
|
|
1144
|
+
readonly code: BillowErrorCode | (string & {});
|
|
1145
|
+
/** Structured error context from the server (e.g. per-field validation issues), when present. */
|
|
1146
|
+
readonly details?: unknown;
|
|
1147
|
+
/** billow's per-request id (`x-request-id`) — quote it in a bug report to trace the server log. */
|
|
1148
|
+
readonly requestId?: string | undefined;
|
|
1149
|
+
constructor(status: number, code: BillowErrorCode | (string & {}), message: string, details?: unknown, requestId?: string);
|
|
1150
|
+
}
|
|
1151
|
+
/** Everything a request needs: the transport, the base URL, the bearer, and resilience knobs. */
|
|
1152
|
+
interface RequestContext {
|
|
1153
|
+
fetch: typeof fetch;
|
|
1154
|
+
baseUrl: string;
|
|
1155
|
+
/** The bearer — a secret/publishable API key, or a portal-session token. */
|
|
1156
|
+
bearer: string;
|
|
1157
|
+
timeoutMs: number;
|
|
1158
|
+
maxRetries: number;
|
|
1159
|
+
retryBackoffMs: number;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
/**
|
|
1163
|
+
* Money helpers, mirrored for the SDK (which cannot import the server-side `@billow/core`).
|
|
1164
|
+
* billow stores every amount as integer minor units (e.g. piasters) plus an ISO-4217 currency;
|
|
1165
|
+
* the number of minor units in one major unit depends on the currency's exponent, which is NOT
|
|
1166
|
+
* always 2 (KWD/BHD/OMR are 3, JPY/KRW are 0). Use these instead of a hardcoded `* 100` / `/ 100`,
|
|
1167
|
+
* which silently mis-handles those currencies 10-100x.
|
|
1168
|
+
*
|
|
1169
|
+
* The exponent table mirrors `@billow/core` and is parity-tested against it (see money.test.ts),
|
|
1170
|
+
* so a change in core fails CI until this mirror matches.
|
|
1171
|
+
*/
|
|
1172
|
+
/** The number of digits after the decimal point for `currency` (ISO-4217); defaults to 2. */
|
|
1173
|
+
declare function currencyExponent(currency: string): number;
|
|
1174
|
+
/**
|
|
1175
|
+
* Convert a major-unit amount (e.g. `5.00`) into integer minor units for `currency`, rounded to
|
|
1176
|
+
* the nearest minor unit. Use when building an amount to send to the API.
|
|
1177
|
+
*/
|
|
1178
|
+
declare function toMinorUnits(major: number, currency: string): number;
|
|
1179
|
+
/** Convert integer minor units back to major units for `currency` (the inverse of toMinorUnits). */
|
|
1180
|
+
declare function toMajorUnits(minor: number, currency: string): number;
|
|
1181
|
+
/**
|
|
1182
|
+
* Format integer minor units with their currency for display (e.g. 10000, "EGP" → "EGP 100.00";
|
|
1183
|
+
* 5000, "KWD" → "KWD 5.000"). The currency's exponent drives both the divisor and the decimals.
|
|
1184
|
+
*/
|
|
1185
|
+
declare function formatMoney(minor: number, currency: string): string;
|
|
1186
|
+
|
|
1187
|
+
declare function createChargesResource(ctx: RequestContext): {
|
|
1188
|
+
/** Create a customer-present charge -> returns a hosted checkout URL. Pass an
|
|
1189
|
+
* `idempotencyKey` to make the create safe to retry (with `maxRetries`). */
|
|
1190
|
+
create: (input: CreateChargeInput, options?: RequestOptions) => Promise<Charge>;
|
|
1191
|
+
/** Charge the customer's current saved card without customer presence. */
|
|
1192
|
+
createMerchantInitiated: (input: CreateMerchantInitiatedChargeInput, options: IdempotentRequestOptions) => Promise<Charge>;
|
|
1193
|
+
/** Fetch a charge. Pass `{ sync: true }` to force an authoritative provider pull. */
|
|
1194
|
+
get: (id: string, opts?: {
|
|
1195
|
+
sync?: boolean;
|
|
1196
|
+
} & CallOptions) => Promise<Charge>;
|
|
1197
|
+
/** List charges (paginated). Filters: status, currency, customer (external id), from, to. */
|
|
1198
|
+
list: (params?: ChargeListParams, options?: CallOptions) => ListPromise<ChargeListItem>;
|
|
1199
|
+
/** Download the one-off charge's receipt as a PDF (raw bytes). */
|
|
1200
|
+
receipt: (id: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
1201
|
+
/** Download the immutable credit note for a succeeded refund. */
|
|
1202
|
+
creditNote: (chargeId: string, refundId: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
1203
|
+
/**
|
|
1204
|
+
* Refund a succeeded charge: `{ amount }` (minor units) for a partial, `{}` for its whole
|
|
1205
|
+
* remaining balance. The `idempotencyKey` is required and must identify this one refund
|
|
1206
|
+
* (e.g. your own refund request's id): a retry under it - yours, or the SDK's own
|
|
1207
|
+
* `maxRetries` - answers the same refund, in whatever status, instead of refunding again.
|
|
1208
|
+
* Reuse the key whenever the outcome is unknown (a timeout or dropped connection); a new
|
|
1209
|
+
* key asks for a new refund, e.g. after this one `failed`. `replayed` tells the refund an
|
|
1210
|
+
* earlier request under the key made (`true`) from one this call made (`false`).
|
|
1211
|
+
*
|
|
1212
|
+
* Always check `status`: resolving does not mean refunded. A provider that declines the
|
|
1213
|
+
* refund answers `502 provider_error`, which throws with `maxRetries: 0` (the default); with
|
|
1214
|
+
* `maxRetries > 0` the SDK retries that 502 under the same key, so the call resolves instead
|
|
1215
|
+
* with the declined refund replayed: `status: "failed"`, `replayed: true`.
|
|
1216
|
+
*/
|
|
1217
|
+
refund: (chargeId: string, input: RefundChargeInput, options: IdempotentRequestOptions) => Promise<RefundRequestResult>;
|
|
1218
|
+
/** A charge's refunds, newest first (`needsReview` flags one awaiting an Operator). */
|
|
1219
|
+
listRefunds: (chargeId: string, options?: CallOptions) => Promise<{
|
|
1220
|
+
data: Refund[];
|
|
1221
|
+
}>;
|
|
1222
|
+
/** Reconcile a pending refund with the provider now; resolves to the refund as it stands. */
|
|
1223
|
+
recheckRefund: (chargeId: string, refundId: string, options?: CallOptions) => Promise<Refund>;
|
|
1224
|
+
/**
|
|
1225
|
+
* Record the outcome you verified in the provider dashboard for a refund awaiting review
|
|
1226
|
+
* (`needsReview`): `succeeded` settles it with a credit note, `failed` releases its amount.
|
|
1227
|
+
* A refund with a provider conflict (`providerConflictStatus`) resolves only as `succeeded`.
|
|
1228
|
+
*/
|
|
1229
|
+
resolveRefund: (chargeId: string, refundId: string, input: ResolveRefundInput, options?: CallOptions) => Promise<Refund>;
|
|
1230
|
+
};
|
|
1231
|
+
declare function createCheckoutMethodsResource(ctx: RequestContext): {
|
|
1232
|
+
/** The customer-present methods + fees offered for a currency (for a method picker). */
|
|
1233
|
+
list: (params: {
|
|
1234
|
+
currency: string;
|
|
1235
|
+
}, options?: CallOptions) => Promise<{
|
|
1236
|
+
methods: CheckoutMethodInfo[];
|
|
1237
|
+
}>;
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
declare function createCreditsResource(ctx: RequestContext): {
|
|
1241
|
+
grants: {
|
|
1242
|
+
/**
|
|
1243
|
+
* Grant prepaid credits to a Customer. The `idempotencyKey` is required and must identify
|
|
1244
|
+
* this one grant (e.g. your own promotion or support-ticket id): a retry under it - yours,
|
|
1245
|
+
* or the SDK's own `maxRetries` - answers the same grant instead of granting twice, with
|
|
1246
|
+
* `replayed: true`. Reusing the key for a different grant throws `idempotency_conflict`
|
|
1247
|
+
* (409). Credit quantities are decimal strings of microcredits in both directions.
|
|
1248
|
+
*/
|
|
1249
|
+
create: (input: CreateCreditGrantInput, options: IdempotentRequestOptions) => Promise<CreditGrantRequestResult>;
|
|
1250
|
+
};
|
|
1251
|
+
packs: {
|
|
1252
|
+
/**
|
|
1253
|
+
* The Credit Packs a customer can buy in `currency` (ISO 4217), cheapest first: credits and
|
|
1254
|
+
* bonus (decimal strings of microcredits), price (minor units), and the derived
|
|
1255
|
+
* `pricePerCredit` and `savingsBps` - so your pricing page never hardcodes a price.
|
|
1256
|
+
*/
|
|
1257
|
+
list: (currency: string, options?: CallOptions) => Promise<CreditPacks>;
|
|
1258
|
+
/** Configure a Credit Pack on a one-time catalog Price. */
|
|
1259
|
+
create: (input: CreateCreditPackInput, options?: CallOptions) => Promise<CreditPack>;
|
|
1260
|
+
/** A Credit Pack's configuration, archived or not. */
|
|
1261
|
+
get: (packId: string, options?: CallOptions) => Promise<CreditPack>;
|
|
1262
|
+
/** Edit a pack's terms or Price, or archive it; top-ups already made keep their terms. */
|
|
1263
|
+
update: (packId: string, input: UpdateCreditPackInput, options?: CallOptions) => Promise<CreditPack>;
|
|
1264
|
+
};
|
|
1265
|
+
topUps: {
|
|
1266
|
+
/**
|
|
1267
|
+
* Buy a Credit Pack for a customer: answers the top-up with `checkoutUrl`, the hosted
|
|
1268
|
+
* checkout to send the buyer to. Credits are granted when the payment succeeds (listen for
|
|
1269
|
+
* `credit_top_up.succeeded`). The `idempotencyKey` is required and must identify this one
|
|
1270
|
+
* purchase: a retry under it answers the same top-up as it now stands (`replayed: true`) and
|
|
1271
|
+
* buys nothing again; reusing it for another purchase throws `idempotency_conflict` (409).
|
|
1272
|
+
* A retry can also throw `conflict` (409), with `details.reason`: `checkout_in_progress` -
|
|
1273
|
+
* the first request is still opening the checkout, so retry the same key shortly - or
|
|
1274
|
+
* `checkout_unavailable` - its checkout could not be opened and never will be, so buy again
|
|
1275
|
+
* under a new key.
|
|
1276
|
+
*/
|
|
1277
|
+
create: (input: CreateCreditTopUpInput, options: IdempotentRequestOptions) => Promise<CreditTopUpRequestResult>;
|
|
1278
|
+
/** A top-up as it now stands: status, checkout, grants, and what refunds revoked. */
|
|
1279
|
+
get: (topUpId: string, options?: CallOptions) => Promise<CreditTopUp>;
|
|
1280
|
+
/**
|
|
1281
|
+
* A customer's top-ups (by external id), newest first, optionally of one status.
|
|
1282
|
+
* Auto-paginating by cursor: `await` the first page, `for await (…)` every top-up, or
|
|
1283
|
+
* `.listAll()` to collect them.
|
|
1284
|
+
*/
|
|
1285
|
+
list: (customer: string, params?: CreditTopUpListParams, options?: CallOptions) => CursorListPromise<CreditTopUp>;
|
|
1286
|
+
};
|
|
1287
|
+
balance: {
|
|
1288
|
+
/**
|
|
1289
|
+
* A Customer's credit balance (by external id): spendable, held, consumed this period,
|
|
1290
|
+
* expiring soon, by kind and category, the current period and the threshold level, true at
|
|
1291
|
+
* `asOf`. A Customer with no credit account yet reads as zeros.
|
|
1292
|
+
*/
|
|
1293
|
+
get: (customer: string, options?: CallOptions) => Promise<CreditBalance>;
|
|
1294
|
+
};
|
|
1295
|
+
ledger: {
|
|
1296
|
+
/**
|
|
1297
|
+
* A Customer's credit ledger (by external id), newest first. Auto-paginating by cursor:
|
|
1298
|
+
* `await` the first page, `for await (…)` every entry, or `.listAll()` to collect them -
|
|
1299
|
+
* entries arriving meanwhile never make the walk skip or repeat one.
|
|
1300
|
+
*/
|
|
1301
|
+
list: (customer: string, params?: CursorListParams, options?: CallOptions) => CursorListPromise<CreditLedgerEntry>;
|
|
1302
|
+
};
|
|
1303
|
+
usage: {
|
|
1304
|
+
/**
|
|
1305
|
+
* A Customer's credit consumption (by external id) per UTC day, by Credit Action or
|
|
1306
|
+
* category, over at most 92 days (the 30 ending today by default).
|
|
1307
|
+
*/
|
|
1308
|
+
get: (customer: string, params?: CreditUsageParams, options?: CallOptions) => Promise<CreditUsage>;
|
|
1309
|
+
};
|
|
1310
|
+
};
|
|
1311
|
+
|
|
1312
|
+
declare function createCustomersResource(ctx: RequestContext): {
|
|
1313
|
+
create: (input: {
|
|
1314
|
+
id: string;
|
|
1315
|
+
name?: string;
|
|
1316
|
+
email?: string;
|
|
1317
|
+
phone?: string;
|
|
1318
|
+
/** The customer's tax / VAT registration number, recorded on their invoices. */
|
|
1319
|
+
taxId?: string;
|
|
1320
|
+
}) => Promise<Customer>;
|
|
1321
|
+
get: (externalId: string, options?: CallOptions) => Promise<Customer>;
|
|
1322
|
+
/** List customers (`q` searches external id / email / name). Auto-paginating: `await` the
|
|
1323
|
+
* first page, `for await (…)` every page, or `.listAll()` to collect them. */
|
|
1324
|
+
list: (params?: CustomerListParams, options?: CallOptions) => ListPromise<CustomerListItem>;
|
|
1325
|
+
/** Full per-customer view: profile + subscriptions + charges + cards + balances. */
|
|
1326
|
+
overview: (externalId: string, options?: CallOptions) => Promise<CustomerOverview>;
|
|
1327
|
+
paymentMethods: {
|
|
1328
|
+
list: (customer: string, options?: CallOptions) => Promise<{
|
|
1329
|
+
id: string;
|
|
1330
|
+
brand: string | null;
|
|
1331
|
+
last4: string | null;
|
|
1332
|
+
expMonth: number | null;
|
|
1333
|
+
expYear: number | null;
|
|
1334
|
+
isDefault: boolean;
|
|
1335
|
+
status: "active" | "expired" | "removed";
|
|
1336
|
+
createdAt: string;
|
|
1337
|
+
expiryStatus: "expired" | "unknown" | "valid" | "expiring";
|
|
1338
|
+
canSetDefault: boolean;
|
|
1339
|
+
canRemove: boolean;
|
|
1340
|
+
removalBlockedReason: string | null;
|
|
1341
|
+
}[]>;
|
|
1342
|
+
setDefault: (customer: string, id: string) => Promise<{
|
|
1343
|
+
id: string;
|
|
1344
|
+
brand: string | null;
|
|
1345
|
+
last4: string | null;
|
|
1346
|
+
expMonth: number | null;
|
|
1347
|
+
expYear: number | null;
|
|
1348
|
+
isDefault: boolean;
|
|
1349
|
+
status: "active" | "expired" | "removed";
|
|
1350
|
+
createdAt: string;
|
|
1351
|
+
expiryStatus: "expired" | "unknown" | "valid" | "expiring";
|
|
1352
|
+
canSetDefault: boolean;
|
|
1353
|
+
canRemove: boolean;
|
|
1354
|
+
removalBlockedReason: string | null;
|
|
1355
|
+
}>;
|
|
1356
|
+
remove: (customer: string, id: string) => Promise<{
|
|
1357
|
+
removed: boolean;
|
|
1358
|
+
}>;
|
|
1359
|
+
};
|
|
1360
|
+
/** Export all portable customer data held by Billow. Secret-key only. */
|
|
1361
|
+
exportData: (externalId: string, options?: CallOptions) => Promise<CustomerDataExport>;
|
|
1362
|
+
/** Anonymize PII after access-granting subscriptions have ended. Secret-key only. */
|
|
1363
|
+
anonymize: (externalId: string, options?: CallOptions) => Promise<CustomerAnonymizationResult>;
|
|
1364
|
+
};
|
|
1365
|
+
|
|
1366
|
+
/**
|
|
1367
|
+
* Delivery-failure visibility: the transactional emails and outbound events that
|
|
1368
|
+
* didn't get through. Read-only, tenant-scoped to the key's (project, environment).
|
|
1369
|
+
*/
|
|
1370
|
+
declare function createDeliverabilityResource(ctx: RequestContext): {
|
|
1371
|
+
/** Email deliveries (newest first), optionally filtered by status. Auto-paginating. */
|
|
1372
|
+
emails: (params?: EmailDeliveryListParams, options?: CallOptions) => ListPromise<EmailDeliveryListItem>;
|
|
1373
|
+
/** Outbound events (newest first), optionally filtered by status. Auto-paginating. */
|
|
1374
|
+
events: (params?: OutboxEventListParams, options?: CallOptions) => ListPromise<OutboxEventListItem>;
|
|
1375
|
+
/** Inbound provider webhooks (newest first), optionally filtered by outcome. Auto-paginating. */
|
|
1376
|
+
inbound: (params?: InboundWebhookListParams, options?: CallOptions) => ListPromise<InboundWebhookListItem>;
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
declare function createInvoicesResource(ctx: RequestContext): {
|
|
1380
|
+
/** List invoices. Filters: status, customer (external id), from, to. Auto-paginating. */
|
|
1381
|
+
list: (params?: InvoiceListParams, options?: CallOptions) => ListPromise<InvoiceListItem>;
|
|
1382
|
+
/** Fetch an invoice with its line items. */
|
|
1383
|
+
get: (id: string, options?: CallOptions) => Promise<InvoiceDetail>;
|
|
1384
|
+
/**
|
|
1385
|
+
* Record that an open invoice was paid outside the gateway (bank transfer, cash, cheque).
|
|
1386
|
+
* Settles the invoice and advances the subscription exactly like a gateway payment.
|
|
1387
|
+
* `amount` must equal the invoice total. Operator (secret key) only.
|
|
1388
|
+
*/
|
|
1389
|
+
recordPayment: (id: string, input: RecordExternalPaymentInput) => Promise<ExternalPaymentResult>;
|
|
1390
|
+
/** Open or resume hosted checkout for an existing outstanding invoice. */
|
|
1391
|
+
pay: (id: string, input?: PayInvoiceInput, options?: CallOptions) => Promise<{
|
|
1392
|
+
invoiceId: string;
|
|
1393
|
+
chargeId: string;
|
|
1394
|
+
checkoutUrl: string;
|
|
1395
|
+
status: "failed" | "processing";
|
|
1396
|
+
expiresAt: string;
|
|
1397
|
+
}>;
|
|
1398
|
+
/** Download the invoice as a PDF (raw bytes). */
|
|
1399
|
+
pdf: (id: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
1400
|
+
/** Download the invoice's payment receipt as a PDF (raw bytes; 404 if unpaid). */
|
|
1401
|
+
receipt: (id: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
1402
|
+
};
|
|
1403
|
+
|
|
1404
|
+
/** The marketplace Integration catalog — install / configure / toggle / uninstall (ADR-0008). */
|
|
1405
|
+
declare function createMarketplaceResource(ctx: RequestContext): {
|
|
1406
|
+
/** Every available Integration with this tenant's install state (no secret values). */
|
|
1407
|
+
catalog: (options?: CallOptions) => Promise<CatalogItem[]>;
|
|
1408
|
+
/** One catalog entry by slug. */
|
|
1409
|
+
get: (slug: string, options?: CallOptions) => Promise<CatalogItem>;
|
|
1410
|
+
/** Install or reconfigure an Integration; `values` are the manifest form's field values. */
|
|
1411
|
+
upsert: (slug: string, values: Record<string, unknown>) => Promise<CatalogItem>;
|
|
1412
|
+
/** Enable or disable an installed Integration. */
|
|
1413
|
+
setEnabled: (slug: string, enabled: boolean) => Promise<CatalogItem>;
|
|
1414
|
+
/** Uninstall an Integration. */
|
|
1415
|
+
remove: (slug: string) => Promise<{
|
|
1416
|
+
removed: boolean;
|
|
1417
|
+
}>;
|
|
1418
|
+
/**
|
|
1419
|
+
* Verify an installed Integration's config. An email Integration sends a test
|
|
1420
|
+
* message to `to` (returns `{ sent, to }`); an accounting Integration runs a
|
|
1421
|
+
* non-mutating connectivity check with no recipient (returns `{ ok: true }`).
|
|
1422
|
+
*/
|
|
1423
|
+
test: (slug: string, to?: string) => Promise<{
|
|
1424
|
+
sent: boolean;
|
|
1425
|
+
to: string;
|
|
1426
|
+
} | {
|
|
1427
|
+
ok: true;
|
|
1428
|
+
}>;
|
|
1429
|
+
};
|
|
1430
|
+
|
|
1431
|
+
declare function createMetricsResource(ctx: RequestContext): {
|
|
1432
|
+
/** KPI cards for a currency over a window (`from`/`to` default to the last 30 days). */
|
|
1433
|
+
overview: (params?: MetricsParams, options?: CallOptions) => Promise<MetricsOverview>;
|
|
1434
|
+
/** A single bucketed metric (revenue / mrr / subs / success rate) over a window. */
|
|
1435
|
+
timeseries: (params?: TimeseriesParams, options?: CallOptions) => Promise<TimeseriesResult>;
|
|
1436
|
+
/**
|
|
1437
|
+
* KPIs rolled up into the org's reporting currency across all billing currencies
|
|
1438
|
+
* (Phase H). Resolves to `null` when no reporting currency is configured.
|
|
1439
|
+
*/
|
|
1440
|
+
rollup: (params?: {
|
|
1441
|
+
from?: string;
|
|
1442
|
+
to?: string;
|
|
1443
|
+
}, options?: CallOptions) => Promise<MetricsRollup | null>;
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1446
|
+
declare function createPortalSessionsResource(ctx: RequestContext): {
|
|
1447
|
+
create: (input: CreatePortalSessionInput) => Promise<PortalSession>;
|
|
1448
|
+
};
|
|
1449
|
+
|
|
1450
|
+
declare function createProductsResource(ctx: RequestContext): {
|
|
1451
|
+
/** Define a product (its first active version + prices + entitlements). */
|
|
1452
|
+
create: (input: CreateProductInput) => Promise<{
|
|
1453
|
+
id: string;
|
|
1454
|
+
slug: string;
|
|
1455
|
+
name: string;
|
|
1456
|
+
type: "recurring" | "one_time";
|
|
1457
|
+
isAddOn: boolean;
|
|
1458
|
+
metadata: Record<string, string>;
|
|
1459
|
+
version: number;
|
|
1460
|
+
archived: boolean;
|
|
1461
|
+
prices: {
|
|
1462
|
+
id: string;
|
|
1463
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1464
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
1465
|
+
intervalCount: number;
|
|
1466
|
+
amount: number;
|
|
1467
|
+
currency: string;
|
|
1468
|
+
meterFeature: string | null;
|
|
1469
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
1470
|
+
usageTiers: {
|
|
1471
|
+
upTo: number | null;
|
|
1472
|
+
unitAmount: number;
|
|
1473
|
+
flatAmount?: number | undefined;
|
|
1474
|
+
}[] | null;
|
|
1475
|
+
packageSize: number | null;
|
|
1476
|
+
rateBps: number | null;
|
|
1477
|
+
taxRateBps: number | null;
|
|
1478
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
1479
|
+
}[];
|
|
1480
|
+
entitlements: {
|
|
1481
|
+
feature: string;
|
|
1482
|
+
allowance: number | null;
|
|
1483
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
1484
|
+
rollover: boolean;
|
|
1485
|
+
}[];
|
|
1486
|
+
}>;
|
|
1487
|
+
/**
|
|
1488
|
+
* Update a product: rename, archive/unarchive, and/or edit its prices +
|
|
1489
|
+
* entitlements in place.
|
|
1490
|
+
*/
|
|
1491
|
+
update: (slug: string, input: UpdateProductInput) => Promise<{
|
|
1492
|
+
id: string;
|
|
1493
|
+
slug: string;
|
|
1494
|
+
name: string;
|
|
1495
|
+
type: "recurring" | "one_time";
|
|
1496
|
+
isAddOn: boolean;
|
|
1497
|
+
metadata: Record<string, string>;
|
|
1498
|
+
version: number;
|
|
1499
|
+
archived: boolean;
|
|
1500
|
+
prices: {
|
|
1501
|
+
id: string;
|
|
1502
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1503
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
1504
|
+
intervalCount: number;
|
|
1505
|
+
amount: number;
|
|
1506
|
+
currency: string;
|
|
1507
|
+
meterFeature: string | null;
|
|
1508
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
1509
|
+
usageTiers: {
|
|
1510
|
+
upTo: number | null;
|
|
1511
|
+
unitAmount: number;
|
|
1512
|
+
flatAmount?: number | undefined;
|
|
1513
|
+
}[] | null;
|
|
1514
|
+
packageSize: number | null;
|
|
1515
|
+
rateBps: number | null;
|
|
1516
|
+
taxRateBps: number | null;
|
|
1517
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
1518
|
+
}[];
|
|
1519
|
+
entitlements: {
|
|
1520
|
+
feature: string;
|
|
1521
|
+
allowance: number | null;
|
|
1522
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
1523
|
+
rollover: boolean;
|
|
1524
|
+
}[];
|
|
1525
|
+
}>;
|
|
1526
|
+
/** Fetch a product (active version + prices + entitlements) by slug. */
|
|
1527
|
+
get: (slug: string, options?: CallOptions) => Promise<{
|
|
1528
|
+
id: string;
|
|
1529
|
+
slug: string;
|
|
1530
|
+
name: string;
|
|
1531
|
+
type: "recurring" | "one_time";
|
|
1532
|
+
isAddOn: boolean;
|
|
1533
|
+
metadata: Record<string, string>;
|
|
1534
|
+
version: number;
|
|
1535
|
+
archived: boolean;
|
|
1536
|
+
prices: {
|
|
1537
|
+
id: string;
|
|
1538
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1539
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
1540
|
+
intervalCount: number;
|
|
1541
|
+
amount: number;
|
|
1542
|
+
currency: string;
|
|
1543
|
+
meterFeature: string | null;
|
|
1544
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
1545
|
+
usageTiers: {
|
|
1546
|
+
upTo: number | null;
|
|
1547
|
+
unitAmount: number;
|
|
1548
|
+
flatAmount?: number | undefined;
|
|
1549
|
+
}[] | null;
|
|
1550
|
+
packageSize: number | null;
|
|
1551
|
+
rateBps: number | null;
|
|
1552
|
+
taxRateBps: number | null;
|
|
1553
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
1554
|
+
}[];
|
|
1555
|
+
entitlements: {
|
|
1556
|
+
feature: string;
|
|
1557
|
+
allowance: number | null;
|
|
1558
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
1559
|
+
rollover: boolean;
|
|
1560
|
+
}[];
|
|
1561
|
+
}>;
|
|
1562
|
+
/** List products. `includeArchived` also returns archived ones (for admin views). */
|
|
1563
|
+
list: (params?: {
|
|
1564
|
+
includeArchived?: boolean;
|
|
1565
|
+
}, options?: CallOptions) => Promise<{
|
|
1566
|
+
id: string;
|
|
1567
|
+
slug: string;
|
|
1568
|
+
name: string;
|
|
1569
|
+
type: "recurring" | "one_time";
|
|
1570
|
+
isAddOn: boolean;
|
|
1571
|
+
metadata: Record<string, string>;
|
|
1572
|
+
version: number;
|
|
1573
|
+
archived: boolean;
|
|
1574
|
+
prices: {
|
|
1575
|
+
id: string;
|
|
1576
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1577
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
1578
|
+
intervalCount: number;
|
|
1579
|
+
amount: number;
|
|
1580
|
+
currency: string;
|
|
1581
|
+
meterFeature: string | null;
|
|
1582
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
1583
|
+
usageTiers: {
|
|
1584
|
+
upTo: number | null;
|
|
1585
|
+
unitAmount: number;
|
|
1586
|
+
flatAmount?: number | undefined;
|
|
1587
|
+
}[] | null;
|
|
1588
|
+
packageSize: number | null;
|
|
1589
|
+
rateBps: number | null;
|
|
1590
|
+
taxRateBps: number | null;
|
|
1591
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
1592
|
+
}[];
|
|
1593
|
+
entitlements: {
|
|
1594
|
+
feature: string;
|
|
1595
|
+
allowance: number | null;
|
|
1596
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
1597
|
+
rollover: boolean;
|
|
1598
|
+
}[];
|
|
1599
|
+
}[]>;
|
|
1600
|
+
/** Delete a plan (soft-delete, ADR-0015). */
|
|
1601
|
+
delete: (slug: string) => Promise<void>;
|
|
1602
|
+
/** Migrate every live subscriber of `fromSlug` onto `toSlug`. */
|
|
1603
|
+
migrateSubscribers: (fromSlug: string, toSlug: string) => Promise<MigrationResult>;
|
|
1604
|
+
/** Live-subscriber count per product, keyed by product id. */
|
|
1605
|
+
subscriberCounts: (options?: CallOptions) => Promise<Record<string, number>>;
|
|
1606
|
+
};
|
|
1607
|
+
|
|
1608
|
+
/**
|
|
1609
|
+
* Organization settings (Phase D3, F) — the configurable dunning schedule, usage settlement grace,
|
|
1610
|
+
* the cross-currency reporting currency + FX-rate registry (ADR-0013), and transactional email
|
|
1611
|
+
* template overrides (PRD-10). All secret-key/server-side surface.
|
|
1612
|
+
*/
|
|
1613
|
+
declare function createSettingsResource(ctx: RequestContext): {
|
|
1614
|
+
/** The dunning retry schedule: configured gaps in days (null = default), + the default. */
|
|
1615
|
+
dunning: {
|
|
1616
|
+
get: (options?: CallOptions) => Promise<{
|
|
1617
|
+
retryDays: number[] | null;
|
|
1618
|
+
defaultRetryDays: number[];
|
|
1619
|
+
}>;
|
|
1620
|
+
/** Set the retry gaps (whole days); pass `null`/`[]` to reset to the default. */
|
|
1621
|
+
update: (retryDays: number[] | null) => Promise<{
|
|
1622
|
+
retryDays: number[] | null;
|
|
1623
|
+
defaultRetryDays: number[];
|
|
1624
|
+
}>;
|
|
1625
|
+
};
|
|
1626
|
+
/**
|
|
1627
|
+
* Usage settlement grace (hours): defers *collection* of a boundary-adjacent priced
|
|
1628
|
+
* calendar-meter renewal past the tz month boundary until late usage settles — the billed
|
|
1629
|
+
* windows/amount are unchanged, only the invoice timing shifts. `0` disables it (the default);
|
|
1630
|
+
* a no-op for any subscription without a priced calendar meter. Cap 72h.
|
|
1631
|
+
*/
|
|
1632
|
+
usageSettlementGrace: {
|
|
1633
|
+
get: (options?: CallOptions) => Promise<{
|
|
1634
|
+
graceHours: number;
|
|
1635
|
+
}>;
|
|
1636
|
+
/** Set the grace window in whole hours (0–72); `0` disables. */
|
|
1637
|
+
update: (graceHours: number) => Promise<{
|
|
1638
|
+
graceHours: number;
|
|
1639
|
+
}>;
|
|
1640
|
+
};
|
|
1641
|
+
/** The currency cross-currency reporting rolls up into (null = none configured). */
|
|
1642
|
+
reporting: {
|
|
1643
|
+
get: (options?: CallOptions) => Promise<{
|
|
1644
|
+
reportingCurrency: string | null;
|
|
1645
|
+
}>;
|
|
1646
|
+
/** Set the reporting currency (3-letter ISO), or `null` to clear it. */
|
|
1647
|
+
update: (currency: string | null) => Promise<{
|
|
1648
|
+
reportingCurrency: string | null;
|
|
1649
|
+
}>;
|
|
1650
|
+
};
|
|
1651
|
+
/** The manually-maintained FX rates the per-invoice reporting snapshot draws on. */
|
|
1652
|
+
fxRates: {
|
|
1653
|
+
list: (options?: CallOptions) => Promise<ExchangeRate[]>;
|
|
1654
|
+
/** Upsert one `base → quote` rate (`rate` is the decimal quote-per-base, > 0). */
|
|
1655
|
+
set: (baseCurrency: string, quoteCurrency: string, rate: number) => Promise<ExchangeRate>;
|
|
1656
|
+
/** Remove a `base → quote` rate. */
|
|
1657
|
+
remove: (baseCurrency: string, quoteCurrency: string) => Promise<{
|
|
1658
|
+
removed: boolean;
|
|
1659
|
+
}>;
|
|
1660
|
+
};
|
|
1661
|
+
/** Transactional email templates (PRD-10): per-template subject/message overrides. */
|
|
1662
|
+
emailTemplates: {
|
|
1663
|
+
/** Every template, merged with this project's overrides, in display order. */
|
|
1664
|
+
list: (options?: CallOptions) => Promise<EmailTemplateSetting[]>;
|
|
1665
|
+
/** Update one template's override (validated against its variable allowlist). */
|
|
1666
|
+
update: (key: string, input: UpdateEmailTemplateInput) => Promise<EmailTemplateSetting>;
|
|
1667
|
+
/**
|
|
1668
|
+
* Send a `[Test]`-prefixed sample of one template to `to`. Dashboard-only:
|
|
1669
|
+
* the API rejects developer keys (the dashboard restricts the recipient to
|
|
1670
|
+
* the signed-in operator; a developer key has no such guarantee).
|
|
1671
|
+
*/
|
|
1672
|
+
test: (key: string, to: string) => Promise<{
|
|
1673
|
+
sent: boolean;
|
|
1674
|
+
to: string;
|
|
1675
|
+
}>;
|
|
1676
|
+
};
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
declare function createSubscriptionsResource(ctx: RequestContext): {
|
|
1680
|
+
/** Start a subscription -> returns the subscription plus a hosted checkout URL. `productId`
|
|
1681
|
+
* accepts the product's id or slug. Pass an `idempotencyKey` to make it safe to retry. */
|
|
1682
|
+
create: (input: CreateSubscriptionInput, options?: RequestOptions) => Promise<{
|
|
1683
|
+
id: string;
|
|
1684
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1685
|
+
customerId: string;
|
|
1686
|
+
productVersionId: string;
|
|
1687
|
+
currency: string;
|
|
1688
|
+
currentPeriodStart: string | null;
|
|
1689
|
+
currentPeriodEnd: string | null;
|
|
1690
|
+
trialEnd: string | null;
|
|
1691
|
+
cancelAtPeriodEnd: boolean;
|
|
1692
|
+
scheduledChange: {
|
|
1693
|
+
productVersionId: string;
|
|
1694
|
+
productId: string;
|
|
1695
|
+
productSlug: string;
|
|
1696
|
+
productName: string;
|
|
1697
|
+
effectiveAt: string | null;
|
|
1698
|
+
} | null;
|
|
1699
|
+
canceledAt: string | null;
|
|
1700
|
+
remainingCycles: number | null;
|
|
1701
|
+
defaultPaymentMethodId: string | null;
|
|
1702
|
+
createdAt: string;
|
|
1703
|
+
subscriptionId: string;
|
|
1704
|
+
checkoutSessionId: string | null;
|
|
1705
|
+
invoiceId: string | null;
|
|
1706
|
+
checkoutUrl: string | null;
|
|
1707
|
+
} | {
|
|
1708
|
+
id: null;
|
|
1709
|
+
subscriptionId: null;
|
|
1710
|
+
checkoutSessionId: string | null;
|
|
1711
|
+
status: string;
|
|
1712
|
+
customerId: string | null;
|
|
1713
|
+
productVersionId: string | null;
|
|
1714
|
+
currency: string | null;
|
|
1715
|
+
currentPeriodStart: null;
|
|
1716
|
+
currentPeriodEnd: null;
|
|
1717
|
+
trialEnd: null;
|
|
1718
|
+
cancelAtPeriodEnd: false;
|
|
1719
|
+
scheduledChange: null;
|
|
1720
|
+
canceledAt: null;
|
|
1721
|
+
remainingCycles: number | null;
|
|
1722
|
+
defaultPaymentMethodId: null;
|
|
1723
|
+
createdAt: string;
|
|
1724
|
+
invoiceId: null;
|
|
1725
|
+
checkoutUrl: string | null;
|
|
1726
|
+
}>;
|
|
1727
|
+
/** Grant a free comp subscription (operator action). `productId` accepts the product's id or slug. */
|
|
1728
|
+
comp: (input: {
|
|
1729
|
+
customerId: string;
|
|
1730
|
+
productId: string;
|
|
1731
|
+
currency?: string;
|
|
1732
|
+
}) => Promise<{
|
|
1733
|
+
id: string;
|
|
1734
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1735
|
+
customerId: string;
|
|
1736
|
+
productVersionId: string;
|
|
1737
|
+
currency: string;
|
|
1738
|
+
currentPeriodStart: string | null;
|
|
1739
|
+
currentPeriodEnd: string | null;
|
|
1740
|
+
trialEnd: string | null;
|
|
1741
|
+
cancelAtPeriodEnd: boolean;
|
|
1742
|
+
scheduledChange: {
|
|
1743
|
+
productVersionId: string;
|
|
1744
|
+
productId: string;
|
|
1745
|
+
productSlug: string;
|
|
1746
|
+
productName: string;
|
|
1747
|
+
effectiveAt: string | null;
|
|
1748
|
+
} | null;
|
|
1749
|
+
canceledAt: string | null;
|
|
1750
|
+
remainingCycles: number | null;
|
|
1751
|
+
defaultPaymentMethodId: string | null;
|
|
1752
|
+
createdAt: string;
|
|
1753
|
+
subscriptionId: string;
|
|
1754
|
+
checkoutSessionId: string | null;
|
|
1755
|
+
invoiceId: string | null;
|
|
1756
|
+
checkoutUrl: string | null;
|
|
1757
|
+
}>;
|
|
1758
|
+
/** List subscriptions (paginated). Filters: status, customer (external id). */
|
|
1759
|
+
list: (params?: SubscriptionListParams, options?: CallOptions) => ListPromise<SubscriptionListItem>;
|
|
1760
|
+
get: (id: string, options?: CallOptions) => Promise<{
|
|
1761
|
+
id: string;
|
|
1762
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1763
|
+
customerId: string;
|
|
1764
|
+
productVersionId: string;
|
|
1765
|
+
currency: string;
|
|
1766
|
+
currentPeriodStart: string | null;
|
|
1767
|
+
currentPeriodEnd: string | null;
|
|
1768
|
+
trialEnd: string | null;
|
|
1769
|
+
cancelAtPeriodEnd: boolean;
|
|
1770
|
+
scheduledChange: {
|
|
1771
|
+
productVersionId: string;
|
|
1772
|
+
productId: string;
|
|
1773
|
+
productSlug: string;
|
|
1774
|
+
productName: string;
|
|
1775
|
+
effectiveAt: string | null;
|
|
1776
|
+
} | null;
|
|
1777
|
+
canceledAt: string | null;
|
|
1778
|
+
remainingCycles: number | null;
|
|
1779
|
+
defaultPaymentMethodId: string | null;
|
|
1780
|
+
createdAt: string;
|
|
1781
|
+
customerExternalId: string;
|
|
1782
|
+
productId: string;
|
|
1783
|
+
productSlug: string;
|
|
1784
|
+
productMetadata: Record<string, string>;
|
|
1785
|
+
}>;
|
|
1786
|
+
/**
|
|
1787
|
+
* The single subscription that currently determines the customer's access, resolved by
|
|
1788
|
+
* billow's own rule (access-granting statuses first, then newest) - or `null` if the
|
|
1789
|
+
* customer has none. Prefer this over picking from `list()` yourself: it avoids the
|
|
1790
|
+
* "newer failed-checkout subscription shadows an older active one" selection bug.
|
|
1791
|
+
*/
|
|
1792
|
+
current: (params: {
|
|
1793
|
+
customer: string;
|
|
1794
|
+
}, options?: CallOptions) => Promise<{
|
|
1795
|
+
id: string;
|
|
1796
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1797
|
+
customerId: string;
|
|
1798
|
+
productVersionId: string;
|
|
1799
|
+
currency: string;
|
|
1800
|
+
currentPeriodStart: string | null;
|
|
1801
|
+
currentPeriodEnd: string | null;
|
|
1802
|
+
trialEnd: string | null;
|
|
1803
|
+
cancelAtPeriodEnd: boolean;
|
|
1804
|
+
scheduledChange: {
|
|
1805
|
+
productVersionId: string;
|
|
1806
|
+
productId: string;
|
|
1807
|
+
productSlug: string;
|
|
1808
|
+
productName: string;
|
|
1809
|
+
effectiveAt: string | null;
|
|
1810
|
+
} | null;
|
|
1811
|
+
canceledAt: string | null;
|
|
1812
|
+
remainingCycles: number | null;
|
|
1813
|
+
defaultPaymentMethodId: string | null;
|
|
1814
|
+
createdAt: string;
|
|
1815
|
+
customerExternalId: string;
|
|
1816
|
+
productId: string;
|
|
1817
|
+
productSlug: string;
|
|
1818
|
+
productMetadata: Record<string, string>;
|
|
1819
|
+
} | null>;
|
|
1820
|
+
/** Cancel — immediately, or at period end with `{ atPeriodEnd: true }`. */
|
|
1821
|
+
cancel: (id: string, opts?: {
|
|
1822
|
+
atPeriodEnd?: boolean;
|
|
1823
|
+
}) => Promise<{
|
|
1824
|
+
id: string;
|
|
1825
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1826
|
+
customerId: string;
|
|
1827
|
+
productVersionId: string;
|
|
1828
|
+
currency: string;
|
|
1829
|
+
currentPeriodStart: string | null;
|
|
1830
|
+
currentPeriodEnd: string | null;
|
|
1831
|
+
trialEnd: string | null;
|
|
1832
|
+
cancelAtPeriodEnd: boolean;
|
|
1833
|
+
scheduledChange: {
|
|
1834
|
+
productVersionId: string;
|
|
1835
|
+
productId: string;
|
|
1836
|
+
productSlug: string;
|
|
1837
|
+
productName: string;
|
|
1838
|
+
effectiveAt: string | null;
|
|
1839
|
+
} | null;
|
|
1840
|
+
canceledAt: string | null;
|
|
1841
|
+
remainingCycles: number | null;
|
|
1842
|
+
defaultPaymentMethodId: string | null;
|
|
1843
|
+
createdAt: string;
|
|
1844
|
+
}>;
|
|
1845
|
+
/** Reverse a scheduled period-end cancellation. Duplicate calls are safe. */
|
|
1846
|
+
resumeCancellation: (id: string) => Promise<{
|
|
1847
|
+
id: string;
|
|
1848
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1849
|
+
customerId: string;
|
|
1850
|
+
productVersionId: string;
|
|
1851
|
+
currency: string;
|
|
1852
|
+
currentPeriodStart: string | null;
|
|
1853
|
+
currentPeriodEnd: string | null;
|
|
1854
|
+
trialEnd: string | null;
|
|
1855
|
+
cancelAtPeriodEnd: boolean;
|
|
1856
|
+
scheduledChange: {
|
|
1857
|
+
productVersionId: string;
|
|
1858
|
+
productId: string;
|
|
1859
|
+
productSlug: string;
|
|
1860
|
+
productName: string;
|
|
1861
|
+
effectiveAt: string | null;
|
|
1862
|
+
} | null;
|
|
1863
|
+
canceledAt: string | null;
|
|
1864
|
+
remainingCycles: number | null;
|
|
1865
|
+
defaultPaymentMethodId: string | null;
|
|
1866
|
+
createdAt: string;
|
|
1867
|
+
}>;
|
|
1868
|
+
pause: (id: string) => Promise<{
|
|
1869
|
+
id: string;
|
|
1870
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1871
|
+
customerId: string;
|
|
1872
|
+
productVersionId: string;
|
|
1873
|
+
currency: string;
|
|
1874
|
+
currentPeriodStart: string | null;
|
|
1875
|
+
currentPeriodEnd: string | null;
|
|
1876
|
+
trialEnd: string | null;
|
|
1877
|
+
cancelAtPeriodEnd: boolean;
|
|
1878
|
+
scheduledChange: {
|
|
1879
|
+
productVersionId: string;
|
|
1880
|
+
productId: string;
|
|
1881
|
+
productSlug: string;
|
|
1882
|
+
productName: string;
|
|
1883
|
+
effectiveAt: string | null;
|
|
1884
|
+
} | null;
|
|
1885
|
+
canceledAt: string | null;
|
|
1886
|
+
remainingCycles: number | null;
|
|
1887
|
+
defaultPaymentMethodId: string | null;
|
|
1888
|
+
createdAt: string;
|
|
1889
|
+
}>;
|
|
1890
|
+
resume: (id: string) => Promise<{
|
|
1891
|
+
id: string;
|
|
1892
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1893
|
+
customerId: string;
|
|
1894
|
+
productVersionId: string;
|
|
1895
|
+
currency: string;
|
|
1896
|
+
currentPeriodStart: string | null;
|
|
1897
|
+
currentPeriodEnd: string | null;
|
|
1898
|
+
trialEnd: string | null;
|
|
1899
|
+
cancelAtPeriodEnd: boolean;
|
|
1900
|
+
scheduledChange: {
|
|
1901
|
+
productVersionId: string;
|
|
1902
|
+
productId: string;
|
|
1903
|
+
productSlug: string;
|
|
1904
|
+
productName: string;
|
|
1905
|
+
effectiveAt: string | null;
|
|
1906
|
+
} | null;
|
|
1907
|
+
canceledAt: string | null;
|
|
1908
|
+
remainingCycles: number | null;
|
|
1909
|
+
defaultPaymentMethodId: string | null;
|
|
1910
|
+
createdAt: string;
|
|
1911
|
+
}>;
|
|
1912
|
+
/** Apply a coupon to an existing subscription. */
|
|
1913
|
+
applyCoupon: (id: string, code: string) => Promise<{
|
|
1914
|
+
id: string;
|
|
1915
|
+
couponId: string;
|
|
1916
|
+
cyclesRemaining: number | null;
|
|
1917
|
+
}>;
|
|
1918
|
+
/** Change plan — immediate prorated upgrade, or downgrade scheduled for period end. `productId` accepts the product's id or slug. */
|
|
1919
|
+
changePlan: (id: string, productId: string) => Promise<{
|
|
1920
|
+
id: string;
|
|
1921
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1922
|
+
customerId: string;
|
|
1923
|
+
productVersionId: string;
|
|
1924
|
+
currency: string;
|
|
1925
|
+
currentPeriodStart: string | null;
|
|
1926
|
+
currentPeriodEnd: string | null;
|
|
1927
|
+
trialEnd: string | null;
|
|
1928
|
+
cancelAtPeriodEnd: boolean;
|
|
1929
|
+
scheduledChange: {
|
|
1930
|
+
productVersionId: string;
|
|
1931
|
+
productId: string;
|
|
1932
|
+
productSlug: string;
|
|
1933
|
+
productName: string;
|
|
1934
|
+
effectiveAt: string | null;
|
|
1935
|
+
} | null;
|
|
1936
|
+
canceledAt: string | null;
|
|
1937
|
+
remainingCycles: number | null;
|
|
1938
|
+
defaultPaymentMethodId: string | null;
|
|
1939
|
+
createdAt: string;
|
|
1940
|
+
} & {
|
|
1941
|
+
change: "upgrade" | "downgrade" | "noop";
|
|
1942
|
+
prorationInvoiceId: string | null;
|
|
1943
|
+
chargeStatus: string | null;
|
|
1944
|
+
}>;
|
|
1945
|
+
/** Clear a pending downgrade. Duplicate calls are safe. */
|
|
1946
|
+
clearScheduledPlanChange: (id: string) => Promise<{
|
|
1947
|
+
id: string;
|
|
1948
|
+
status: "active" | "incomplete" | "incomplete_expired" | "trialing" | "past_due" | "paused" | "canceled" | "unpaid";
|
|
1949
|
+
customerId: string;
|
|
1950
|
+
productVersionId: string;
|
|
1951
|
+
currency: string;
|
|
1952
|
+
currentPeriodStart: string | null;
|
|
1953
|
+
currentPeriodEnd: string | null;
|
|
1954
|
+
trialEnd: string | null;
|
|
1955
|
+
cancelAtPeriodEnd: boolean;
|
|
1956
|
+
scheduledChange: {
|
|
1957
|
+
productVersionId: string;
|
|
1958
|
+
productId: string;
|
|
1959
|
+
productSlug: string;
|
|
1960
|
+
productName: string;
|
|
1961
|
+
effectiveAt: string | null;
|
|
1962
|
+
} | null;
|
|
1963
|
+
canceledAt: string | null;
|
|
1964
|
+
remainingCycles: number | null;
|
|
1965
|
+
defaultPaymentMethodId: string | null;
|
|
1966
|
+
createdAt: string;
|
|
1967
|
+
}>;
|
|
1968
|
+
items: {
|
|
1969
|
+
/** List a subscription's items (base + add-ons). */
|
|
1970
|
+
list: (id: string, options?: CallOptions) => Promise<{
|
|
1971
|
+
id: string;
|
|
1972
|
+
product: string;
|
|
1973
|
+
productSlug: string;
|
|
1974
|
+
priceId: string;
|
|
1975
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1976
|
+
amount: number;
|
|
1977
|
+
currency: string;
|
|
1978
|
+
quantity: number;
|
|
1979
|
+
isAddOn: boolean;
|
|
1980
|
+
isBase: boolean;
|
|
1981
|
+
}[]>;
|
|
1982
|
+
/** Attach an add-on Product. `productId` accepts the product's id or slug. */
|
|
1983
|
+
add: (id: string, productId: string, quantity?: number) => Promise<{
|
|
1984
|
+
id: string;
|
|
1985
|
+
product: string;
|
|
1986
|
+
productSlug: string;
|
|
1987
|
+
priceId: string;
|
|
1988
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
1989
|
+
amount: number;
|
|
1990
|
+
currency: string;
|
|
1991
|
+
quantity: number;
|
|
1992
|
+
isAddOn: boolean;
|
|
1993
|
+
isBase: boolean;
|
|
1994
|
+
}>;
|
|
1995
|
+
/** Change an item's quantity (seats). */
|
|
1996
|
+
updateQuantity: (id: string, itemId: string, quantity: number) => Promise<{
|
|
1997
|
+
id: string;
|
|
1998
|
+
product: string;
|
|
1999
|
+
productSlug: string;
|
|
2000
|
+
priceId: string;
|
|
2001
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
2002
|
+
amount: number;
|
|
2003
|
+
currency: string;
|
|
2004
|
+
quantity: number;
|
|
2005
|
+
isAddOn: boolean;
|
|
2006
|
+
isBase: boolean;
|
|
2007
|
+
}>;
|
|
2008
|
+
/** Detach an add-on item. */
|
|
2009
|
+
remove: (id: string, itemId: string) => Promise<{
|
|
2010
|
+
removed: boolean;
|
|
2011
|
+
}>;
|
|
2012
|
+
};
|
|
2013
|
+
};
|
|
2014
|
+
|
|
2015
|
+
declare function createWebhookEndpointsResource(ctx: RequestContext): {
|
|
2016
|
+
/** Register an endpoint. The signing secret is returned once. */
|
|
2017
|
+
create: (input: CreateWebhookEndpointInput) => Promise<WebhookEndpointWithSecret>;
|
|
2018
|
+
/** List endpoints (newest first; secrets are never returned). Auto-paginating. */
|
|
2019
|
+
list: (params?: ListParams, options?: CallOptions) => ListPromise<WebhookEndpoint>;
|
|
2020
|
+
/** Fetch one endpoint by id. */
|
|
2021
|
+
get: (id: string, options?: CallOptions) => Promise<WebhookEndpoint>;
|
|
2022
|
+
/** Update an endpoint's URL, enabled flag, or event filter. */
|
|
2023
|
+
update: (id: string, input: UpdateWebhookEndpointInput) => Promise<WebhookEndpoint>;
|
|
2024
|
+
/** Delete an endpoint and its delivery history. */
|
|
2025
|
+
delete: (id: string) => Promise<void>;
|
|
2026
|
+
/** Rotate the signing secret — the new plaintext is returned once. */
|
|
2027
|
+
rotateSecret: (id: string) => Promise<WebhookEndpointWithSecret>;
|
|
2028
|
+
/** List delivery attempts for an endpoint (newest first). Auto-paginating. */
|
|
2029
|
+
deliveries: (id: string, params?: ListParams, options?: CallOptions) => ListPromise<WebhookDelivery>;
|
|
2030
|
+
};
|
|
2031
|
+
|
|
2032
|
+
/**
|
|
2033
|
+
* billow client SDK — the "two lines of code" surface, mirroring Autumn's shape
|
|
2034
|
+
* (CONTEXT/ARCHITECTURE §10). A thin typed wrapper over the billow REST API.
|
|
2035
|
+
*
|
|
2036
|
+
* const billow = new Billow(process.env.BILLOW_SECRET_KEY!);
|
|
2037
|
+
* const { allowed } = await billow.check({ customerId, featureId: "projects" });
|
|
2038
|
+
*
|
|
2039
|
+
* Public request/response types live in ./types and are re-exported here, so the
|
|
2040
|
+
* package root stays the single import surface. They are contract-derived and inlined
|
|
2041
|
+
* into the shipped .d.ts at build time (tsup `dts.resolve` reads @billow/contracts'
|
|
2042
|
+
* bundled dist), so the declarations carry no bare `@billow/contracts` import a
|
|
2043
|
+
* consumer couldn't resolve.
|
|
2044
|
+
*
|
|
2045
|
+
* We deliberately do NOT re-export @billow/contracts' runtime zod schemas: a client
|
|
2046
|
+
* SDK shouldn't ship validation - the server is the schema authority - and
|
|
2047
|
+
* re-exporting them made @billow/contracts (a private, unpublished workspace package)
|
|
2048
|
+
* a runtime dependency that left the published SDK impossible to install. Contracts is
|
|
2049
|
+
* now a devDependency. The types are zod-inferred, so the declarations do reference
|
|
2050
|
+
* `zod` (a small, published package kept as a runtime dependency); the runtime bundle
|
|
2051
|
+
* itself imports neither zod nor @billow/contracts.
|
|
2052
|
+
*/
|
|
2053
|
+
|
|
2054
|
+
declare class Billow {
|
|
2055
|
+
#private;
|
|
2056
|
+
customers: ReturnType<typeof createCustomersResource>;
|
|
2057
|
+
charges: ReturnType<typeof createChargesResource>;
|
|
2058
|
+
checkoutMethods: ReturnType<typeof createCheckoutMethodsResource>;
|
|
2059
|
+
/** Prepaid credits: grant them to a Customer (quantities are decimal strings of microcredits). */
|
|
2060
|
+
credits: ReturnType<typeof createCreditsResource>;
|
|
2061
|
+
invoices: ReturnType<typeof createInvoicesResource>;
|
|
2062
|
+
metrics: ReturnType<typeof createMetricsResource>;
|
|
2063
|
+
webhookEndpoints: ReturnType<typeof createWebhookEndpointsResource>;
|
|
2064
|
+
products: ReturnType<typeof createProductsResource>;
|
|
2065
|
+
subscriptions: ReturnType<typeof createSubscriptionsResource>;
|
|
2066
|
+
portalSessions: ReturnType<typeof createPortalSessionsResource>;
|
|
2067
|
+
deliverability: ReturnType<typeof createDeliverabilityResource>;
|
|
2068
|
+
marketplace: ReturnType<typeof createMarketplaceResource>;
|
|
2069
|
+
/**
|
|
2070
|
+
* Organization settings (Phase D3, F) — the configurable dunning schedule, usage settlement grace,
|
|
2071
|
+
* and the cross-currency reporting currency + FX-rate registry (ADR-0013).
|
|
2072
|
+
*/
|
|
2073
|
+
settings: ReturnType<typeof createSettingsResource>;
|
|
2074
|
+
constructor(apiKey: string, opts?: BillowOptions);
|
|
2075
|
+
coupons: {
|
|
2076
|
+
/** Define a coupon (a reusable discount template). */
|
|
2077
|
+
create: (input: CreateCouponInput) => Promise<Coupon>;
|
|
2078
|
+
/** List coupons (secret key only — enumerates live promo codes). Auto-paginating. */
|
|
2079
|
+
list: (params?: ListParams, options?: CallOptions) => ListPromise<Coupon>;
|
|
2080
|
+
/** Deactivate a coupon (existing discounts keep running). */
|
|
2081
|
+
deactivate: (id: string) => Promise<Coupon>;
|
|
2082
|
+
};
|
|
2083
|
+
/** Manage developer webhook endpoints — register, rotate secrets, inspect deliveries.
|
|
2084
|
+
* (To VERIFY incoming deliveries, import `constructEvent` from `@usebillow/sdk/webhooks`.) */
|
|
2085
|
+
features: {
|
|
2086
|
+
/** Define a feature (a boolean access gate, or a metered feature with a meter). */
|
|
2087
|
+
create: (input: {
|
|
2088
|
+
slug: string;
|
|
2089
|
+
name: string;
|
|
2090
|
+
kind: FeatureKind;
|
|
2091
|
+
meter?: MeterConfig;
|
|
2092
|
+
}) => Promise<Feature>;
|
|
2093
|
+
/**
|
|
2094
|
+
* Edit a feature in place: its `name`, and — for a metered feature — its `meter`
|
|
2095
|
+
* aggregation. The server refuses a meter change once usage has been recorded (it
|
|
2096
|
+
* would rewrite billed history), so set the meter right at create time or before you
|
|
2097
|
+
* start tracking. Returns the updated feature.
|
|
2098
|
+
*/
|
|
2099
|
+
update: (slug: string, input: UpdateFeatureInput) => Promise<Feature>;
|
|
2100
|
+
/** List features in the tenant. Auto-paginating. */
|
|
2101
|
+
list: (params?: ListParams, options?: CallOptions) => ListPromise<Feature>;
|
|
2102
|
+
/**
|
|
2103
|
+
* Usage Alerts + Spend caps on a metered feature (Phase C). A `threshold`
|
|
2104
|
+
* Alert notifies (webhook + optional customer email) as usage crosses its
|
|
2105
|
+
* thresholds; a `cap` blocks `check` once reached.
|
|
2106
|
+
*/
|
|
2107
|
+
alerts: {
|
|
2108
|
+
/** List the alerts + spend cap on a metered feature (by slug). */
|
|
2109
|
+
list: (feature: string, options?: CallOptions) => Promise<UsageAlert[]>;
|
|
2110
|
+
/** Define an Alert or Spend cap on a metered feature. */
|
|
2111
|
+
create: (feature: string, input: CreateUsageAlertInput) => Promise<UsageAlert>;
|
|
2112
|
+
/** Delete one alert/cap rule by id. */
|
|
2113
|
+
remove: (feature: string, id: string) => Promise<{
|
|
2114
|
+
removed: boolean;
|
|
2115
|
+
}>;
|
|
2116
|
+
};
|
|
2117
|
+
};
|
|
2118
|
+
integrations: {
|
|
2119
|
+
/** The registered payment providers + their config manifests (drives the picker + form). */
|
|
2120
|
+
providers: (options?: CallOptions) => Promise<PaymentProviderDefinition[]>;
|
|
2121
|
+
/** List configured credential sets per currency (provider + non-secret config). Secret-only. */
|
|
2122
|
+
list: (options?: CallOptions) => Promise<ProviderCredentialSummary[]>;
|
|
2123
|
+
/**
|
|
2124
|
+
* Verify a provider's configuration against its live API. Pass `currency` to
|
|
2125
|
+
* choose a credential set and `target` to probe one verify target (Paymob: a
|
|
2126
|
+
* method); pass `sampleToken` (SANDBOX ONLY) to run a functional sub-test.
|
|
2127
|
+
* This probe hits the provider's live API (mutates nothing here), so it takes a
|
|
2128
|
+
* per-call {@link CallOptions} for a timeout / cancellation — `opts` is spread into
|
|
2129
|
+
* the body, so `options` stays a separate trailing arg (never merged in).
|
|
2130
|
+
*/
|
|
2131
|
+
verify: (provider: string, opts?: {
|
|
2132
|
+
currency?: string;
|
|
2133
|
+
target?: string;
|
|
2134
|
+
sampleToken?: string;
|
|
2135
|
+
}, options?: CallOptions) => Promise<ProviderVerifyResult>;
|
|
2136
|
+
/** Manage stored payment-provider credentials (the dashboard's "manage credentials" forms). */
|
|
2137
|
+
credentials: {
|
|
2138
|
+
/** The editable view of stored credential sets (secrets are never returned). */
|
|
2139
|
+
list: (options?: CallOptions) => Promise<CredentialSet[]>;
|
|
2140
|
+
/** Create or rotate a (provider, currency) credential set. */
|
|
2141
|
+
upsert: (input: UpsertCredentialsInput) => Promise<CredentialSet>;
|
|
2142
|
+
/** Delete a (provider, currency) credential set. */
|
|
2143
|
+
remove: (provider: string, currency: string) => Promise<{
|
|
2144
|
+
removed: boolean;
|
|
2145
|
+
}>;
|
|
2146
|
+
};
|
|
2147
|
+
};
|
|
2148
|
+
/** The merchant's business identity — the seller block on documents and email from-name. */
|
|
2149
|
+
businessProfile: {
|
|
2150
|
+
/** The stored profile, or null if one was never saved. */
|
|
2151
|
+
get: (options?: CallOptions) => Promise<BusinessProfile | null>;
|
|
2152
|
+
/** Create or update the profile; omit a field to keep it, send "" to clear it. */
|
|
2153
|
+
update: (input: UpdateBusinessProfileInput) => Promise<BusinessProfile>;
|
|
2154
|
+
};
|
|
2155
|
+
/**
|
|
2156
|
+
* Hosted customer surfaces (Phase G, ADR-0014). Mint a portal session for one of
|
|
2157
|
+
* your signed-in users and redirect them to the returned `url` — the self-serve
|
|
2158
|
+
* portal, or a `checkout` hand-off for `productId`. The Customer's own calls go
|
|
2159
|
+
* through {@link BillowPortal}, constructed with the session token.
|
|
2160
|
+
*/
|
|
2161
|
+
/** Identity of this key's tenant — org, environment, configured currencies. */
|
|
2162
|
+
me(options?: CallOptions): Promise<Whoami>;
|
|
2163
|
+
/**
|
|
2164
|
+
* Global search (PRD-12) across customers, invoices, subscriptions, and charges
|
|
2165
|
+
* for the key's `(project, environment)`. Bounded per entity (default 5, max 10);
|
|
2166
|
+
* a blank query returns empty results. Backs the dashboard's ⌘K palette.
|
|
2167
|
+
*/
|
|
2168
|
+
search(q: string, limit?: number, options?: CallOptions): Promise<SearchResults>;
|
|
2169
|
+
/**
|
|
2170
|
+
* Gate access to a feature. `featureId` is the feature slug. Returns
|
|
2171
|
+
* `{ allowed, balance }` — `balance` is `null` for unlimited/boolean features.
|
|
2172
|
+
*/
|
|
2173
|
+
check(input: {
|
|
2174
|
+
customerId: string;
|
|
2175
|
+
featureId: string;
|
|
2176
|
+
}, options?: CallOptions): Promise<CheckResult>;
|
|
2177
|
+
/**
|
|
2178
|
+
* Record usage of a metered feature (`value` defaults to 1; negative credits
|
|
2179
|
+
* back). Pass `idempotencyKey` to make a retried call a no-op — which also makes the call
|
|
2180
|
+
* safe to retry automatically when `maxRetries` is set.
|
|
2181
|
+
*/
|
|
2182
|
+
track(input: {
|
|
2183
|
+
customerId: string;
|
|
2184
|
+
featureId: string;
|
|
2185
|
+
value?: number;
|
|
2186
|
+
/** Arbitrary event properties — used by meter filters and property-based aggregations. */
|
|
2187
|
+
properties?: Record<string, string | number>;
|
|
2188
|
+
idempotencyKey?: string;
|
|
2189
|
+
/**
|
|
2190
|
+
* When the usage occurred (ISO-8601). Defaults to now; backdate it to land a value in a
|
|
2191
|
+
* still-open reset window (e.g. a finalized month-end total). Rejected if more than 5 minutes
|
|
2192
|
+
* in the future or more than 7 days in the past.
|
|
2193
|
+
*/
|
|
2194
|
+
occurredAt?: string;
|
|
2195
|
+
}, options?: CallOptions): Promise<TrackResult>;
|
|
2196
|
+
/** List a customer's live entitlements (one per feature). */
|
|
2197
|
+
entitlements(customerId: string, options?: CallOptions): Promise<{
|
|
2198
|
+
entitlements: EntitlementView[];
|
|
2199
|
+
}>;
|
|
2200
|
+
/** Start a subscription → returns a hosted checkout URL to redirect the customer to. */
|
|
2201
|
+
attach(input: CreateSubscriptionInput, options?: RequestOptions): Promise<AttachResult>;
|
|
2202
|
+
}
|
|
2203
|
+
/**
|
|
2204
|
+
* The browser-safe client: construct it with a **publishable** key (`bl_<env>_pk_…`)
|
|
2205
|
+
* to read the public catalog from any origin (CORS-enabled). It exposes ONLY public,
|
|
2206
|
+
* project-scoped reads — products and their prices — so it is safe to ship in a
|
|
2207
|
+
* frontend bundle. Customer-scoped data (entitlements, checkout) is never reachable
|
|
2208
|
+
* with a publishable key; use the server handler or a portal session for that.
|
|
2209
|
+
*/
|
|
2210
|
+
declare class BillowPublishable {
|
|
2211
|
+
#private;
|
|
2212
|
+
constructor(publishableKey: string, opts?: BillowOptions);
|
|
2213
|
+
products: {
|
|
2214
|
+
/** The active catalog — products and their prices, for a pricing table. */
|
|
2215
|
+
list: (options?: CallOptions) => Promise<{
|
|
2216
|
+
id: string;
|
|
2217
|
+
slug: string;
|
|
2218
|
+
name: string;
|
|
2219
|
+
type: "recurring" | "one_time";
|
|
2220
|
+
isAddOn: boolean;
|
|
2221
|
+
metadata: Record<string, string>;
|
|
2222
|
+
version: number;
|
|
2223
|
+
archived: boolean;
|
|
2224
|
+
prices: {
|
|
2225
|
+
id: string;
|
|
2226
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
2227
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
2228
|
+
intervalCount: number;
|
|
2229
|
+
amount: number;
|
|
2230
|
+
currency: string;
|
|
2231
|
+
meterFeature: string | null;
|
|
2232
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
2233
|
+
usageTiers: {
|
|
2234
|
+
upTo: number | null;
|
|
2235
|
+
unitAmount: number;
|
|
2236
|
+
flatAmount?: number | undefined;
|
|
2237
|
+
}[] | null;
|
|
2238
|
+
packageSize: number | null;
|
|
2239
|
+
rateBps: number | null;
|
|
2240
|
+
taxRateBps: number | null;
|
|
2241
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
2242
|
+
}[];
|
|
2243
|
+
entitlements: {
|
|
2244
|
+
feature: string;
|
|
2245
|
+
allowance: number | null;
|
|
2246
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
2247
|
+
rollover: boolean;
|
|
2248
|
+
}[];
|
|
2249
|
+
}[]>;
|
|
2250
|
+
/** Fetch one active product (with its prices) by slug. */
|
|
2251
|
+
get: (slug: string, options?: CallOptions) => Promise<{
|
|
2252
|
+
id: string;
|
|
2253
|
+
slug: string;
|
|
2254
|
+
name: string;
|
|
2255
|
+
type: "recurring" | "one_time";
|
|
2256
|
+
isAddOn: boolean;
|
|
2257
|
+
metadata: Record<string, string>;
|
|
2258
|
+
version: number;
|
|
2259
|
+
archived: boolean;
|
|
2260
|
+
prices: {
|
|
2261
|
+
id: string;
|
|
2262
|
+
kind: "one_time" | "fixed_recurring" | "licensed" | "usage";
|
|
2263
|
+
interval: "day" | "week" | "month" | "year" | null;
|
|
2264
|
+
intervalCount: number;
|
|
2265
|
+
amount: number;
|
|
2266
|
+
currency: string;
|
|
2267
|
+
meterFeature: string | null;
|
|
2268
|
+
usageModel: "graduated" | "volume" | "package" | "percentage" | "stairstep" | null;
|
|
2269
|
+
usageTiers: {
|
|
2270
|
+
upTo: number | null;
|
|
2271
|
+
unitAmount: number;
|
|
2272
|
+
flatAmount?: number | undefined;
|
|
2273
|
+
}[] | null;
|
|
2274
|
+
packageSize: number | null;
|
|
2275
|
+
rateBps: number | null;
|
|
2276
|
+
taxRateBps: number | null;
|
|
2277
|
+
taxBehavior: "inclusive" | "exclusive" | null;
|
|
2278
|
+
}[];
|
|
2279
|
+
entitlements: {
|
|
2280
|
+
feature: string;
|
|
2281
|
+
allowance: number | null;
|
|
2282
|
+
resetInterval: "day" | "week" | "month" | "year" | null;
|
|
2283
|
+
rollover: boolean;
|
|
2284
|
+
}[];
|
|
2285
|
+
}>;
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* The customer-surface client (Phase G, ADR-0014): construct it with a portal
|
|
2290
|
+
* session token (minted by your backend via `billow.portalSessions.create`) to act
|
|
2291
|
+
* as that one Customer. It exposes only their own data — no operator/secret-key
|
|
2292
|
+
* surface — so the token can be held by a hosted portal app safely.
|
|
2293
|
+
*/
|
|
2294
|
+
declare class BillowPortal {
|
|
2295
|
+
#private;
|
|
2296
|
+
constructor(sessionToken: string, opts?: BillowOptions);
|
|
2297
|
+
/** The portal shell: flow, return URL, merchant brand, and customer identity —
|
|
2298
|
+
* the lightweight payload the hosting app frames every page with, and the
|
|
2299
|
+
* validate-and-route check at login. */
|
|
2300
|
+
session(options?: CallOptions): Promise<PortalSessionInfo>;
|
|
2301
|
+
/** The self-serve home payload: identity + subscriptions + usage + saved cards. */
|
|
2302
|
+
me(options?: CallOptions): Promise<PortalView>;
|
|
2303
|
+
invoices: {
|
|
2304
|
+
/** The Customer's invoices (newest first). Auto-paginating. */
|
|
2305
|
+
list: (params?: ListParams & {
|
|
2306
|
+
status?: InvoiceListItem["status"];
|
|
2307
|
+
}, options?: CallOptions) => ListPromise<InvoiceListItem>;
|
|
2308
|
+
/** Open or resume checkout for this customer's outstanding invoice. */
|
|
2309
|
+
pay: (id: string, input?: PayInvoiceInput, options?: CallOptions) => Promise<{
|
|
2310
|
+
invoiceId: string;
|
|
2311
|
+
chargeId: string;
|
|
2312
|
+
checkoutUrl: string;
|
|
2313
|
+
status: "failed" | "processing";
|
|
2314
|
+
expiresAt: string;
|
|
2315
|
+
}>;
|
|
2316
|
+
/** Download one of the Customer's invoices as a PDF (raw bytes). */
|
|
2317
|
+
pdf: (id: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
2318
|
+
/** Download the payment receipt for one of the Customer's invoices (raw bytes). */
|
|
2319
|
+
receiptPdf: (id: string, options?: CallOptions) => Promise<ArrayBuffer>;
|
|
2320
|
+
};
|
|
2321
|
+
subscriptions: {
|
|
2322
|
+
/** Schedule one of the Customer's subscriptions to cancel at period end. */
|
|
2323
|
+
cancel: (id: string) => Promise<PortalSubscriptionStatus>;
|
|
2324
|
+
/** Reverse a scheduled period-end cancellation. */
|
|
2325
|
+
resumeCancellation: (id: string) => Promise<PortalSubscriptionStatus>;
|
|
2326
|
+
/** Move one of the Customer's subscriptions to another plan (upgrade now / downgrade scheduled). */
|
|
2327
|
+
changePlan: (id: string, productId: string) => Promise<PortalPlanChange>;
|
|
2328
|
+
/** Clear a pending downgrade. */
|
|
2329
|
+
clearScheduledPlanChange: (id: string) => Promise<PortalSubscriptionStatus>;
|
|
2330
|
+
};
|
|
2331
|
+
paymentMethod: {
|
|
2332
|
+
/** Open a checkout to save or replace the Customer's card (zero-amount tokenization). */
|
|
2333
|
+
update: (returnUrl?: string) => Promise<PortalCardSetupResult>;
|
|
2334
|
+
};
|
|
2335
|
+
paymentMethods: {
|
|
2336
|
+
list: (options?: CallOptions) => Promise<{
|
|
2337
|
+
id: string;
|
|
2338
|
+
brand: string | null;
|
|
2339
|
+
last4: string | null;
|
|
2340
|
+
expMonth: number | null;
|
|
2341
|
+
expYear: number | null;
|
|
2342
|
+
isDefault: boolean;
|
|
2343
|
+
status: "active" | "expired" | "removed";
|
|
2344
|
+
createdAt: string;
|
|
2345
|
+
expiryStatus: "expired" | "unknown" | "valid" | "expiring";
|
|
2346
|
+
canSetDefault: boolean;
|
|
2347
|
+
canRemove: boolean;
|
|
2348
|
+
removalBlockedReason: string | null;
|
|
2349
|
+
}[]>;
|
|
2350
|
+
setDefault: (id: string) => Promise<{
|
|
2351
|
+
id: string;
|
|
2352
|
+
brand: string | null;
|
|
2353
|
+
last4: string | null;
|
|
2354
|
+
expMonth: number | null;
|
|
2355
|
+
expYear: number | null;
|
|
2356
|
+
isDefault: boolean;
|
|
2357
|
+
status: "active" | "expired" | "removed";
|
|
2358
|
+
createdAt: string;
|
|
2359
|
+
expiryStatus: "expired" | "unknown" | "valid" | "expiring";
|
|
2360
|
+
canSetDefault: boolean;
|
|
2361
|
+
canRemove: boolean;
|
|
2362
|
+
removalBlockedReason: string | null;
|
|
2363
|
+
}>;
|
|
2364
|
+
remove: (id: string) => Promise<{
|
|
2365
|
+
removed: boolean;
|
|
2366
|
+
}>;
|
|
2367
|
+
};
|
|
2368
|
+
/** The checkout hand-off, for a session minted with `flow: "checkout"`. */
|
|
2369
|
+
checkout: {
|
|
2370
|
+
/** The plan being confirmed (product + base price). */
|
|
2371
|
+
get: (options?: CallOptions) => Promise<PortalCheckout>;
|
|
2372
|
+
/** Subscribe to the plan → returns the hosted Paymob checkout URL to redirect to. */
|
|
2373
|
+
start: () => Promise<{
|
|
2374
|
+
checkoutUrl: string | null;
|
|
2375
|
+
}>;
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
export { AttachResult, BILLOW_ERROR_CODES, Billow, BillowApiError, type BillowErrorCode, BillowOptions, BillowPortal, BillowPublishable, type BusinessProfile, CallOptions, type CatalogItem, Charge, type ChargeListItem, type ChargeListParams, type ChargeSearchHit, ChargeStatus, CheckResult, type CheckoutMethodInfo, type ConfigField, type ConfigFieldOption, type ConfigFieldType, Coupon, CreateChargeInput, CreateCouponInput, CreateCreditGrantInput, CreateCreditPackInput, CreateCreditTopUpInput, CreateMerchantInitiatedChargeInput, type CreatePortalSessionInput, CreateProductInput, CreateSubscriptionInput, CreateUsageAlertInput, type CreateWebhookEndpointInput, type CredentialSet, CreditBalance, CreditGrant, CreditGrantRequestResult, CreditLedgerEntry, CreditPack, CreditPacks, CreditThresholdLevel, CreditTopUp, CreditTopUpListParams, CreditTopUpRequestResult, CreditUsage, CreditUsageParams, type CursorListParams, type CursorListPromise, type CursorPaginated, Customer, type CustomerAnonymizationResult, type CustomerCreditsExport, type CustomerDataExport, type CustomerListItem, type CustomerListParams, type CustomerOverview, type CustomerSearchHit, type CustomerUsage, type CustomerUsageDetail, type EmailDeliveryListItem, type EmailDeliveryListParams, type EmailDeliveryStatus, type EmailTemplateSetting, EntitlementView, type ExchangeRate, type ExportJsonValue, type ExternalPaymentMethod, type ExternalPaymentResult, Feature, FeatureKind, IdempotentRequestOptions, type InboundWebhookListItem, type InboundWebhookListParams, type InboundWebhookOutcome, type IntegrationDefinition, type IntegrationKind, type IntegrationTier, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListItem, type InvoiceListParams, type InvoiceSearchHit, InvoiceStatus, type ListParams, type ListPromise, MeterConfig, type MetricsOverview, type MetricsParams, type MetricsRollup, MigrationResult, type OutboxEventListItem, type OutboxEventListParams, type OutboxEventStatus, type Paginated, PayInvoiceInput, type PaymentMethod, PaymentMethodStatus, type PaymentProviderDefinition, type PortalCardSetupResult, type PortalCheckout, type PortalPlanChange, type PortalSession, type PortalSessionFlow, type PortalSessionInfo, type PortalSubscriptionStatus, type PortalView, type ProviderCredentialSummary, type ProviderVerifyResult, type ProviderVerifyTarget, type ProviderVerifyTargetResult, type RecordExternalPaymentInput, type Refund, type RefundChargeInput, type RefundRequestResult, type RefundReviewReason, RefundStatus, RequestOptions, type ResolveRefundInput, SavedPaymentMethod, type ScheduledSubscriptionChange, type SearchResults, type SubscriptionListItem, type SubscriptionListParams, type SubscriptionSearchHit, SubscriptionStatus, TaxBehavior, type TimeseriesInterval, type TimeseriesMetric, type TimeseriesParams, type TimeseriesPoint, type TimeseriesResult, TrackResult, UnappliedPaymentReason, type UpdateBusinessProfileInput, UpdateCreditPackInput, type UpdateEmailTemplateInput, UpdateFeatureInput, UpdateProductInput, type UpdateWebhookEndpointInput, type UpsertCredentialsInput, UsageAlert, type WebhookDelivery, WebhookDeliveryStatus, type WebhookEndpoint, type WebhookEndpointWithSecret, type Whoami, currencyExponent, formatMoney, isSecretField, toMajorUnits, toMinorUnits };
|