@soledgic/sdk 0.2.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/dist/index.mjs ADDED
@@ -0,0 +1,2183 @@
1
+ // src/errors.ts
2
+ var SoledgicError = class extends Error {
3
+ constructor(message, status, details, code) {
4
+ super(message);
5
+ this.status = status;
6
+ this.details = details;
7
+ this.code = code;
8
+ this.name = "SoledgicError";
9
+ }
10
+ };
11
+ var ValidationError = class extends SoledgicError {
12
+ constructor(message, details, code = "VALIDATION_ERROR") {
13
+ super(message, 400, details, code);
14
+ this.name = "ValidationError";
15
+ }
16
+ };
17
+ var AuthenticationError = class extends SoledgicError {
18
+ constructor(message = "Invalid API key", details, code = "AUTHENTICATION_ERROR") {
19
+ super(message, 401, details, code);
20
+ this.name = "AuthenticationError";
21
+ }
22
+ };
23
+ var NotFoundError = class extends SoledgicError {
24
+ constructor(message, details, code = "NOT_FOUND") {
25
+ super(message, 404, details, code);
26
+ this.name = "NotFoundError";
27
+ }
28
+ };
29
+ var ConflictError = class extends SoledgicError {
30
+ constructor(message, details, code = "CONFLICT") {
31
+ super(message, 409, details, code);
32
+ this.name = "ConflictError";
33
+ }
34
+ };
35
+
36
+ // src/webhooks.ts
37
+ function isArrayBufferView(value) {
38
+ return typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value);
39
+ }
40
+ function webhookPayloadToString(payload) {
41
+ if (typeof payload === "string") {
42
+ return payload;
43
+ }
44
+ if (payload instanceof ArrayBuffer) {
45
+ return new TextDecoder().decode(new Uint8Array(payload));
46
+ }
47
+ if (isArrayBufferView(payload)) {
48
+ return new TextDecoder().decode(payload);
49
+ }
50
+ return JSON.stringify(payload);
51
+ }
52
+ function timingSafeEqual(a, b) {
53
+ const aLen = a.length;
54
+ const bLen = b.length;
55
+ const maxLen = Math.max(aLen, bLen);
56
+ let result = aLen ^ bLen;
57
+ for (let i = 0; i < maxLen; i++) {
58
+ const aChar = i < aLen ? a.charCodeAt(i) : 0;
59
+ const bChar = i < bLen ? b.charCodeAt(i) : 0;
60
+ result |= aChar ^ bChar;
61
+ }
62
+ return result === 0;
63
+ }
64
+ async function hmacHex(secret, payload) {
65
+ if (!globalThis.crypto?.subtle) {
66
+ throw new Error("Web Crypto API is not available in this runtime");
67
+ }
68
+ const key = await globalThis.crypto.subtle.importKey(
69
+ "raw",
70
+ new TextEncoder().encode(secret),
71
+ { name: "HMAC", hash: "SHA-256" },
72
+ false,
73
+ ["sign"]
74
+ );
75
+ const signature = await globalThis.crypto.subtle.sign("HMAC", key, new TextEncoder().encode(payload));
76
+ return Array.from(new Uint8Array(signature)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
77
+ }
78
+ function parseWebhookSignatureHeader(signatureHeader) {
79
+ if (!signatureHeader) {
80
+ return { timestamp: null, v1Signatures: [] };
81
+ }
82
+ let timestamp = null;
83
+ const v1Signatures = [];
84
+ for (const part of signatureHeader.split(",")) {
85
+ const [key, value] = part.trim().split("=");
86
+ if (!key || !value) continue;
87
+ if (key === "t") {
88
+ const numeric = Number(value);
89
+ timestamp = Number.isFinite(numeric) ? numeric : null;
90
+ } else if (key === "v1") {
91
+ v1Signatures.push(value);
92
+ }
93
+ }
94
+ return { timestamp, v1Signatures };
95
+ }
96
+ function toEpochSeconds(value) {
97
+ if (value instanceof Date) {
98
+ return Math.floor(value.getTime() / 1e3);
99
+ }
100
+ if (typeof value === "number" && Number.isFinite(value)) {
101
+ return Math.floor(value);
102
+ }
103
+ return Math.floor(Date.now() / 1e3);
104
+ }
105
+ async function verifyWebhookSignature(payload, signatureHeader, secret, options = {}) {
106
+ const payloadString = webhookPayloadToString(payload);
107
+ const parsed = parseWebhookSignatureHeader(signatureHeader);
108
+ if (parsed.timestamp === null || parsed.v1Signatures.length === 0) {
109
+ return false;
110
+ }
111
+ const toleranceSeconds = options.toleranceSeconds ?? 300;
112
+ if (toleranceSeconds > 0) {
113
+ const nowSeconds = toEpochSeconds(options.now);
114
+ if (Math.abs(nowSeconds - parsed.timestamp) > toleranceSeconds) {
115
+ return false;
116
+ }
117
+ }
118
+ const expected = await hmacHex(secret, `${parsed.timestamp}.${payloadString}`);
119
+ return parsed.v1Signatures.some((signature) => timingSafeEqual(signature, expected));
120
+ }
121
+ function parseWebhookEvent(payload) {
122
+ const payloadString = webhookPayloadToString(payload);
123
+ const parsed = JSON.parse(payloadString);
124
+ const type = typeof parsed.type === "string" ? parsed.type : typeof parsed.event === "string" ? parsed.event : "unknown";
125
+ return {
126
+ id: typeof parsed.id === "string" ? parsed.id : null,
127
+ type,
128
+ createdAt: typeof parsed.created_at === "string" ? parsed.created_at : null,
129
+ livemode: typeof parsed.livemode === "boolean" ? parsed.livemode : null,
130
+ data: parsed.data ?? null,
131
+ raw: parsed
132
+ };
133
+ }
134
+
135
+ // src/helpers.ts
136
+ function mapWebhookEndpoint(endpoint) {
137
+ return {
138
+ id: String(endpoint?.id ?? ""),
139
+ url: typeof endpoint?.url === "string" ? endpoint.url : "",
140
+ description: typeof endpoint?.description === "string" ? endpoint.description : null,
141
+ events: Array.isArray(endpoint?.events) ? endpoint.events.filter((event) => typeof event === "string") : [],
142
+ isActive: Boolean(endpoint?.is_active),
143
+ createdAt: typeof endpoint?.created_at === "string" ? endpoint.created_at : "",
144
+ secretRotatedAt: typeof endpoint?.secret_rotated_at === "string" ? endpoint.secret_rotated_at : null
145
+ };
146
+ }
147
+ function resolveWebhookEndpointUrl(webhookEndpoints, endpointUrl) {
148
+ if (typeof endpointUrl === "string") {
149
+ return endpointUrl;
150
+ }
151
+ if (Array.isArray(webhookEndpoints)) {
152
+ const first = webhookEndpoints[0];
153
+ return typeof first?.url === "string" ? first.url : null;
154
+ }
155
+ if (webhookEndpoints && typeof webhookEndpoints === "object" && typeof webhookEndpoints.url === "string") {
156
+ return webhookEndpoints.url;
157
+ }
158
+ return null;
159
+ }
160
+ function mapWebhookDelivery(delivery) {
161
+ return {
162
+ id: String(delivery?.id ?? ""),
163
+ endpointId: typeof delivery?.endpoint_id === "string" ? delivery.endpoint_id : null,
164
+ endpointUrl: resolveWebhookEndpointUrl(delivery?.webhook_endpoints, delivery?.endpoint_url),
165
+ eventType: typeof delivery?.event_type === "string" ? delivery.event_type : "unknown",
166
+ status: typeof delivery?.status === "string" ? delivery.status : "unknown",
167
+ attempts: Number(delivery?.attempts || 0),
168
+ maxAttempts: typeof delivery?.max_attempts === "number" ? delivery.max_attempts : null,
169
+ responseStatus: typeof delivery?.response_status === "number" ? delivery.response_status : null,
170
+ responseBody: typeof delivery?.response_body === "string" ? delivery.response_body : null,
171
+ responseTimeMs: typeof delivery?.response_time_ms === "number" ? delivery.response_time_ms : null,
172
+ createdAt: typeof delivery?.created_at === "string" ? delivery.created_at : "",
173
+ deliveredAt: typeof delivery?.delivered_at === "string" ? delivery.delivered_at : null,
174
+ nextRetryAt: typeof delivery?.next_retry_at === "string" ? delivery.next_retry_at : null,
175
+ payload: delivery?.payload && typeof delivery.payload === "object" ? delivery.payload : null
176
+ };
177
+ }
178
+
179
+ // src/client.ts
180
+ var DEFAULT_API_VERSION = "2026-03-01";
181
+ var DEFAULT_BASE_URL = "https://api.soledgic.com/v1";
182
+ var Soledgic = class {
183
+ constructor(config) {
184
+ this.webhooks = {
185
+ verifySignature: (payload, signatureHeader, secret, options) => verifyWebhookSignature(payload, signatureHeader, secret, options),
186
+ parseEvent: (payload) => parseWebhookEvent(payload)
187
+ };
188
+ if (!config.apiKey) {
189
+ throw new Error("apiKey is required");
190
+ }
191
+ let key = config.apiKey;
192
+ this._getKey = () => {
193
+ if (!key) throw new Error("Client has been destroyed");
194
+ return key;
195
+ };
196
+ this._destroyKey = () => {
197
+ key = null;
198
+ };
199
+ this.baseUrl = (config.baseUrl?.trim() || DEFAULT_BASE_URL).replace(/\/$/, "");
200
+ this.timeoutMs = config.timeout ?? 3e4;
201
+ this.apiVersion = (config.apiVersion || "").trim() || DEFAULT_API_VERSION;
202
+ }
203
+ /** Clear the API key from memory. After calling destroy(), all requests will throw. */
204
+ destroy() {
205
+ this._destroyKey?.();
206
+ }
207
+ throwTypedError(message, status, data) {
208
+ const apiCode = typeof data?.error_code === "string" ? data.error_code : typeof data?.code === "string" ? data.code : void 0;
209
+ switch (status) {
210
+ case 400:
211
+ throw new ValidationError(message, data, apiCode);
212
+ case 401:
213
+ throw new AuthenticationError(message, data, apiCode);
214
+ case 404:
215
+ throw new NotFoundError(message, data, apiCode);
216
+ case 409:
217
+ throw new ConflictError(message, data, apiCode);
218
+ default:
219
+ throw new SoledgicError(message, status, data, apiCode);
220
+ }
221
+ }
222
+ async request(endpoint, body) {
223
+ const controller = new AbortController();
224
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
225
+ try {
226
+ const response = await fetch(`${this.baseUrl}/${endpoint}`, {
227
+ method: "POST",
228
+ headers: {
229
+ "x-api-key": this._getKey(),
230
+ "Content-Type": "application/json",
231
+ "Soledgic-Version": this.apiVersion
232
+ },
233
+ body: JSON.stringify(body),
234
+ signal: controller.signal
235
+ });
236
+ const data = await response.json();
237
+ if (!response.ok) {
238
+ this.throwTypedError(
239
+ data.error || `Request failed: ${response.status}`,
240
+ response.status,
241
+ data
242
+ );
243
+ }
244
+ return data;
245
+ } finally {
246
+ clearTimeout(timer);
247
+ }
248
+ }
249
+ async requestGet(endpoint, params) {
250
+ const url = new URL(`${this.baseUrl}/${endpoint}`);
251
+ if (params) {
252
+ for (const [key, value] of Object.entries(params)) {
253
+ if (value !== void 0) url.searchParams.set(key, String(value));
254
+ }
255
+ }
256
+ const controller = new AbortController();
257
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
258
+ try {
259
+ const response = await fetch(url.toString(), {
260
+ method: "GET",
261
+ headers: {
262
+ "x-api-key": this._getKey(),
263
+ "Soledgic-Version": this.apiVersion
264
+ },
265
+ signal: controller.signal
266
+ });
267
+ const data = await response.json();
268
+ if (!response.ok) {
269
+ this.throwTypedError(
270
+ data.error || `Request failed: ${response.status}`,
271
+ response.status,
272
+ data
273
+ );
274
+ }
275
+ return data;
276
+ } finally {
277
+ clearTimeout(timer);
278
+ }
279
+ }
280
+ async requestRaw(endpoint, body) {
281
+ const controller = new AbortController();
282
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
283
+ try {
284
+ const response = await fetch(`${this.baseUrl}/${endpoint}`, {
285
+ method: "POST",
286
+ headers: {
287
+ "x-api-key": this._getKey(),
288
+ "Content-Type": "application/json",
289
+ "Soledgic-Version": this.apiVersion
290
+ },
291
+ body: JSON.stringify(body),
292
+ signal: controller.signal
293
+ });
294
+ if (!response.ok) {
295
+ const text = await response.text();
296
+ let parsed;
297
+ try {
298
+ parsed = JSON.parse(text);
299
+ } catch {
300
+ parsed = { error: text };
301
+ }
302
+ this.throwTypedError(
303
+ parsed.error || `Request failed: ${response.status}`,
304
+ response.status,
305
+ parsed
306
+ );
307
+ }
308
+ return response;
309
+ } finally {
310
+ clearTimeout(timer);
311
+ }
312
+ }
313
+ async requestGetRaw(endpoint, params) {
314
+ const url = new URL(`${this.baseUrl}/${endpoint}`);
315
+ if (params) {
316
+ for (const [key, value] of Object.entries(params)) {
317
+ if (value !== void 0) url.searchParams.set(key, String(value));
318
+ }
319
+ }
320
+ const controller = new AbortController();
321
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
322
+ try {
323
+ const response = await fetch(url.toString(), {
324
+ method: "GET",
325
+ headers: {
326
+ "x-api-key": this._getKey(),
327
+ "Soledgic-Version": this.apiVersion
328
+ },
329
+ signal: controller.signal
330
+ });
331
+ if (!response.ok) {
332
+ const text = await response.text();
333
+ let parsed;
334
+ try {
335
+ parsed = JSON.parse(text);
336
+ } catch {
337
+ parsed = { error: text };
338
+ }
339
+ this.throwTypedError(
340
+ parsed.error || `Request failed: ${response.status}`,
341
+ response.status,
342
+ parsed
343
+ );
344
+ }
345
+ return response;
346
+ } finally {
347
+ clearTimeout(timer);
348
+ }
349
+ }
350
+ async requestDelete(endpoint) {
351
+ const controller = new AbortController();
352
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
353
+ try {
354
+ const response = await fetch(`${this.baseUrl}/${endpoint}`, {
355
+ method: "DELETE",
356
+ headers: {
357
+ "x-api-key": this._getKey(),
358
+ "Soledgic-Version": this.apiVersion
359
+ },
360
+ signal: controller.signal
361
+ });
362
+ const data = await response.json();
363
+ if (!response.ok) {
364
+ this.throwTypedError(
365
+ data.error || `Request failed: ${response.status}`,
366
+ response.status,
367
+ data
368
+ );
369
+ }
370
+ return data;
371
+ } finally {
372
+ clearTimeout(timer);
373
+ }
374
+ }
375
+ // === STANDARD MODE - INCOME & EXPENSES ===
376
+ async recordIncome(req) {
377
+ return this.request("record-income", {
378
+ reference_id: req.referenceId,
379
+ amount: req.amount,
380
+ description: req.description,
381
+ category: req.category,
382
+ customer_id: req.customerId,
383
+ customer_name: req.customerName,
384
+ received_to: req.receivedTo,
385
+ invoice_id: req.invoiceId,
386
+ transaction_date: req.transactionDate,
387
+ metadata: req.metadata
388
+ });
389
+ }
390
+ async recordExpense(req) {
391
+ return this.request("record-expense", {
392
+ reference_id: req.referenceId,
393
+ amount: req.amount,
394
+ description: req.description,
395
+ category: req.category,
396
+ vendor_id: req.vendorId,
397
+ vendor_name: req.vendorName,
398
+ paid_from: req.paidFrom,
399
+ receipt_url: req.receiptUrl,
400
+ tax_deductible: req.taxDeductible,
401
+ transaction_date: req.transactionDate,
402
+ metadata: req.metadata,
403
+ authorizing_instrument_id: req.authorizingInstrumentId,
404
+ risk_evaluation_id: req.riskEvaluationId,
405
+ authorization_decision_id: req.authorizationDecisionId
406
+ });
407
+ }
408
+ async recordBill(req) {
409
+ return this.request("record-bill", {
410
+ amount: req.amount,
411
+ description: req.description,
412
+ vendor_name: req.vendorName,
413
+ vendor_id: req.vendorId,
414
+ reference_id: req.referenceId,
415
+ due_date: req.dueDate,
416
+ expense_category: req.expenseCategory,
417
+ paid: req.paid,
418
+ metadata: req.metadata,
419
+ authorizing_instrument_id: req.authorizingInstrumentId,
420
+ risk_evaluation_id: req.riskEvaluationId,
421
+ authorization_decision_id: req.authorizationDecisionId
422
+ });
423
+ }
424
+ // === AUTHORIZING INSTRUMENTS ===
425
+ // Register financial authorization instruments for transaction validation
426
+ // Instruments are immutable and ledger-adjacent - they explain WHY money moved
427
+ async registerInstrument(req) {
428
+ return this.request("register-instrument", {
429
+ external_ref: req.externalRef,
430
+ extracted_terms: {
431
+ amount: req.extractedTerms.amount,
432
+ currency: req.extractedTerms.currency,
433
+ cadence: req.extractedTerms.cadence,
434
+ counterparty_name: req.extractedTerms.counterpartyName
435
+ }
436
+ });
437
+ }
438
+ // === SHADOW LEDGER (GHOST ENTRIES) ===
439
+ // Project future obligations based on authorizing instrument terms.
440
+ // Ghost entries NEVER affect balances or entries - only express future intent.
441
+ async projectIntent(req) {
442
+ const response = await this.request("project-intent", {
443
+ authorizing_instrument_id: req.authorizingInstrumentId,
444
+ until_date: req.untilDate,
445
+ horizon_count: req.horizonCount
446
+ });
447
+ return {
448
+ success: response.success,
449
+ instrumentId: response.instrument_id,
450
+ externalRef: response.external_ref,
451
+ cadence: response.cadence,
452
+ projectionsCreated: response.projections_created,
453
+ projectionsRequested: response.projections_requested,
454
+ duplicatesSkipped: response.duplicates_skipped,
455
+ dateRange: response.date_range,
456
+ projectedDates: response.projected_dates
457
+ };
458
+ }
459
+ // === REVERSALS & CORRECTIONS ===
460
+ async reverseTransaction(req) {
461
+ const response = await this.request("reverse-transaction", {
462
+ transaction_id: req.transactionId,
463
+ reason: req.reason,
464
+ partial_amount: req.partialAmount,
465
+ idempotency_key: req.idempotencyKey,
466
+ metadata: req.metadata
467
+ });
468
+ return {
469
+ success: response.success,
470
+ voidType: response.void_type,
471
+ message: response.message,
472
+ transactionId: response.transaction_id ?? response.original_transaction_id ?? req.transactionId,
473
+ reversalId: response.reversal_id ?? null,
474
+ reversedAmount: response.reversed_amount ?? null,
475
+ isPartial: response.is_partial ?? null,
476
+ voidedAt: response.voided_at ?? null,
477
+ reversedAt: response.reversed_at ?? null,
478
+ warning: response.warning ?? null
479
+ };
480
+ }
481
+ // === PERIOD MANAGEMENT ===
482
+ async listPeriods() {
483
+ return this.request("close-period", { action: "list" });
484
+ }
485
+ async createPeriod(req) {
486
+ return this.request("close-period", {
487
+ action: "create",
488
+ start_date: req.startDate,
489
+ end_date: req.endDate,
490
+ name: req.name
491
+ });
492
+ }
493
+ async closePeriod(year, month, quarter) {
494
+ return this.request("close-period", { year, month, quarter });
495
+ }
496
+ // === RECONCILIATION ===
497
+ async matchTransaction(req) {
498
+ const response = await this.request("reconciliations/matches", {
499
+ transaction_id: req.transactionId,
500
+ bank_transaction_id: req.bankTransactionId
501
+ });
502
+ return {
503
+ success: response.success,
504
+ match: {
505
+ id: response.match.id,
506
+ transactionId: response.match.transaction_id,
507
+ bankTransactionId: response.match.bank_transaction_id,
508
+ status: response.match.status,
509
+ matchedAt: response.match.matched_at
510
+ }
511
+ };
512
+ }
513
+ async unmatchTransaction(transactionId) {
514
+ const response = await this.requestDelete(`reconciliations/matches/${transactionId}`);
515
+ return {
516
+ success: response.success,
517
+ deleted: Boolean(response.deleted),
518
+ transactionId: response.transaction_id
519
+ };
520
+ }
521
+ async listUnmatchedTransactions() {
522
+ const response = await this.requestGet("reconciliations/unmatched");
523
+ return {
524
+ success: response.success,
525
+ unmatchedCount: response.unmatched_count ?? 0,
526
+ transactions: (response.transactions || []).map((transaction) => ({
527
+ id: transaction.id,
528
+ referenceId: transaction.reference_id ?? null,
529
+ description: transaction.description ?? null,
530
+ amount: transaction.amount,
531
+ currency: transaction.currency || "USD",
532
+ createdAt: transaction.created_at,
533
+ status: transaction.status,
534
+ metadata: transaction.metadata || {}
535
+ }))
536
+ };
537
+ }
538
+ async createReconciliationSnapshot(req) {
539
+ const response = await this.request("reconciliations/snapshots", {
540
+ period_id: req.periodId,
541
+ as_of_date: req.asOfDate
542
+ });
543
+ return {
544
+ success: response.success,
545
+ snapshot_id: response.snapshot.id,
546
+ integrity_hash: response.snapshot.integrity_hash
547
+ };
548
+ }
549
+ async getReconciliationSnapshot(periodId) {
550
+ const response = await this.requestGet(`reconciliations/snapshots/${periodId}`);
551
+ return {
552
+ success: response.success,
553
+ snapshot: {
554
+ id: response.snapshot.id,
555
+ periodStart: response.snapshot.period_start,
556
+ periodEnd: response.snapshot.period_end,
557
+ integrityHash: response.snapshot.integrity_hash,
558
+ integrityValid: Boolean(response.snapshot.integrity_valid),
559
+ summary: {
560
+ totalMatched: response.snapshot.summary?.total_matched ?? 0,
561
+ totalUnmatched: response.snapshot.summary?.total_unmatched ?? 0,
562
+ matchedAmount: response.snapshot.summary?.matched_amount ?? 0,
563
+ unmatchedAmount: response.snapshot.summary?.unmatched_amount ?? 0
564
+ }
565
+ }
566
+ };
567
+ }
568
+ async autoMatchBankTransaction(bankAggregatorTransactionId) {
569
+ const response = await this.request("reconciliations/auto-match", {
570
+ bank_aggregator_transaction_id: bankAggregatorTransactionId
571
+ });
572
+ return {
573
+ success: response.success,
574
+ result: {
575
+ matched: Boolean(response.result?.matched),
576
+ matchType: response.result?.match_type ?? null,
577
+ matchedTransactionId: response.result?.matched_transaction_id ?? null,
578
+ bankAggregatorTransactionId: response.result?.bank_aggregator_transaction_id ?? bankAggregatorTransactionId
579
+ }
580
+ };
581
+ }
582
+ // === FROZEN STATEMENTS ===
583
+ async generateFrozenStatements(periodId) {
584
+ return this.request("frozen-statements", {
585
+ action: "generate",
586
+ period_id: periodId
587
+ });
588
+ }
589
+ async getFrozenStatement(periodId, statementType) {
590
+ return this.request("frozen-statements", {
591
+ action: "get",
592
+ period_id: periodId,
593
+ statement_type: statementType
594
+ });
595
+ }
596
+ async listFrozenStatements(periodId) {
597
+ return this.request("frozen-statements", {
598
+ action: "list",
599
+ period_id: periodId
600
+ });
601
+ }
602
+ async verifyFrozenStatements(periodId) {
603
+ return this.request("frozen-statements", {
604
+ action: "verify",
605
+ period_id: periodId
606
+ });
607
+ }
608
+ // === SPLITS MANAGEMENT ===
609
+ async listTiers() {
610
+ return this.request("manage-splits", { action: "list_tiers" });
611
+ }
612
+ async getEffectiveSplit(creatorId) {
613
+ return this.request("manage-splits", { action: "get_effective_split", creator_id: creatorId });
614
+ }
615
+ async setCreatorSplit(creatorId, splitPercent) {
616
+ return this.request("manage-splits", { action: "set_creator_split", creator_id: creatorId, split_percent: splitPercent });
617
+ }
618
+ async clearCreatorSplit(creatorId) {
619
+ return this.request("manage-splits", { action: "clear_creator_split", creator_id: creatorId });
620
+ }
621
+ async autoPromoteCreators() {
622
+ return this.request("manage-splits", { action: "auto_promote" });
623
+ }
624
+ async getSummary() {
625
+ const response = await this.requestGet("participants");
626
+ const participants = Array.isArray(response.participants) ? response.participants : [];
627
+ const summary = participants.reduce((totals, participant) => ({
628
+ total_ledger_balance: totals.total_ledger_balance + Number(participant.ledger_balance || 0),
629
+ total_held_amount: totals.total_held_amount + Number(participant.held_amount || 0),
630
+ total_available_balance: totals.total_available_balance + Number(participant.available_balance || 0)
631
+ }), {
632
+ total_ledger_balance: 0,
633
+ total_held_amount: 0,
634
+ total_available_balance: 0
635
+ });
636
+ return {
637
+ success: response.success,
638
+ data: {
639
+ ...summary,
640
+ participant_count: participants.length
641
+ }
642
+ };
643
+ }
644
+ // === REPORTS ===
645
+ async getProfitLoss(startDate, endDate) {
646
+ return this.request("generate-report", { report_type: "profit_loss", start_date: startDate, end_date: endDate });
647
+ }
648
+ async getTrialBalance(asOf) {
649
+ return this.request("generate-report", { report_type: "trial_balance", as_of: asOf });
650
+ }
651
+ async get1099Summary(year) {
652
+ return this.request("generate-report", { report_type: "1099_summary", tax_year: year });
653
+ }
654
+ async getCreatorEarnings(startDate, endDate) {
655
+ return this.request("generate-report", { report_type: "creator_earnings", start_date: startDate, end_date: endDate });
656
+ }
657
+ async getHistoricalEarnings(options = {}) {
658
+ return this.requestGet("earnings", {
659
+ start_date: options.startDate,
660
+ end_date: options.endDate,
661
+ creator_id: options.creatorId,
662
+ granularity: options.granularity
663
+ });
664
+ }
665
+ async getTransactions(startDate, endDate, creatorId) {
666
+ return this.request("generate-report", { report_type: "transaction_history", start_date: startDate, end_date: endDate, creator_id: creatorId });
667
+ }
668
+ // === CREDITS ===
669
+ /** Issue credits to a user. 1000 credits = $1 USD (Soledgic standard rate). */
670
+ async issueCredits(userId, credits, options = {}) {
671
+ return this.request("credits", {
672
+ action: "issue",
673
+ user_id: userId,
674
+ credits,
675
+ reason: options.reason,
676
+ reference_id: options.referenceId
677
+ });
678
+ }
679
+ /** Convert earned credits to spendable balance. Minimum 5000 credits ($5). */
680
+ async convertCredits(userId, credits) {
681
+ return this.request("credits", {
682
+ action: "convert",
683
+ user_id: userId,
684
+ credits
685
+ });
686
+ }
687
+ /** Spend spendable balance on creator content. Amount in cents. Split applies. */
688
+ async redeemCredits(userId, creatorId, amountCents, referenceId, options = {}) {
689
+ return this.request("credits", {
690
+ action: "redeem",
691
+ user_id: userId,
692
+ creator_id: creatorId,
693
+ amount: amountCents,
694
+ reference_id: referenceId,
695
+ description: options.description,
696
+ split_percent: options.splitPercent
697
+ });
698
+ }
699
+ /** Get user's credit balance (unconverted) and spendable balance (converted). */
700
+ async getCreditBalance(userId) {
701
+ return this.request("credits", { action: "balance", user_id: userId });
702
+ }
703
+ // === PDF EXPORTS ===
704
+ async generatePDF(reportType, options = {}) {
705
+ return this.request("generate-pdf", {
706
+ report_type: reportType,
707
+ creator_id: options.creatorId,
708
+ start_date: options.startDate,
709
+ end_date: options.endDate,
710
+ tax_year: options.taxYear,
711
+ period_id: options.periodId
712
+ });
713
+ }
714
+ async getCreatorStatement(creatorId, startDate, endDate) {
715
+ return this.generatePDF("creator_statement", { creatorId, startDate, endDate });
716
+ }
717
+ async getProfitLossPDF(startDate, endDate, periodId) {
718
+ return this.generatePDF("profit_loss", { startDate, endDate, periodId });
719
+ }
720
+ async getTrialBalancePDF() {
721
+ return this.generatePDF("trial_balance", {});
722
+ }
723
+ async get1099PDF(taxYear) {
724
+ return this.generatePDF("1099", { taxYear });
725
+ }
726
+ // === AUTO-EMAIL ===
727
+ async configureEmail(config) {
728
+ return this.request("send-statements", {
729
+ action: "configure",
730
+ email_config: {
731
+ enabled: config.enabled,
732
+ send_day: config.sendDay || 1,
733
+ from_name: config.fromName,
734
+ from_email: config.fromEmail,
735
+ subject_template: config.subjectTemplate,
736
+ body_template: config.bodyTemplate,
737
+ cc_admin: config.ccAdmin,
738
+ admin_email: config.adminEmail
739
+ }
740
+ });
741
+ }
742
+ async sendMonthlyStatements(year, month) {
743
+ return this.request("send-statements", {
744
+ action: "send_monthly_statements",
745
+ year,
746
+ month
747
+ });
748
+ }
749
+ async sendCreatorStatement(creatorId, year, month) {
750
+ return this.request("send-statements", {
751
+ action: "send_single_statement",
752
+ creator_id: creatorId,
753
+ year,
754
+ month
755
+ });
756
+ }
757
+ async previewStatementEmail(creatorId, year, month) {
758
+ return this.request("send-statements", {
759
+ action: "preview",
760
+ creator_id: creatorId,
761
+ year,
762
+ month
763
+ });
764
+ }
765
+ async getEmailHistory() {
766
+ return this.request("send-statements", { action: "get_queue" });
767
+ }
768
+ // === WEBHOOKS ===
769
+ async listWebhookEndpoints() {
770
+ const response = await this.request("webhooks", { action: "list" });
771
+ return {
772
+ success: response.success,
773
+ data: Array.isArray(response.data) ? response.data.map(mapWebhookEndpoint) : []
774
+ };
775
+ }
776
+ async createWebhookEndpoint(config) {
777
+ const response = await this.request("webhooks", {
778
+ action: "create",
779
+ url: config.url,
780
+ description: config.description,
781
+ events: config.events || ["*"]
782
+ });
783
+ return {
784
+ success: response.success,
785
+ data: {
786
+ ...mapWebhookEndpoint(response.data || {}),
787
+ secret: typeof response.data?.secret === "string" ? response.data.secret : null
788
+ },
789
+ message: typeof response.message === "string" ? response.message : void 0
790
+ };
791
+ }
792
+ async updateWebhookEndpoint(endpointId, updates) {
793
+ const response = await this.request("webhooks", {
794
+ action: "update",
795
+ endpoint_id: endpointId,
796
+ url: updates.url,
797
+ description: updates.description,
798
+ events: updates.events,
799
+ is_active: updates.isActive
800
+ });
801
+ return {
802
+ success: response.success,
803
+ data: mapWebhookEndpoint(response.data || {})
804
+ };
805
+ }
806
+ async deleteWebhookEndpoint(endpointId) {
807
+ const response = await this.request("webhooks", { action: "delete", endpoint_id: endpointId });
808
+ return {
809
+ success: response.success,
810
+ message: typeof response.message === "string" ? response.message : void 0
811
+ };
812
+ }
813
+ async testWebhookEndpoint(endpointId) {
814
+ const response = await this.request("webhooks", { action: "test", endpoint_id: endpointId });
815
+ return {
816
+ success: response.success,
817
+ error: typeof response.error === "string" ? response.error : void 0,
818
+ data: {
819
+ delivered: Boolean(response.data?.delivered),
820
+ status: typeof response.data?.status === "number" ? response.data.status : null,
821
+ responseTimeMs: typeof response.data?.response_time_ms === "number" ? response.data.response_time_ms : null
822
+ }
823
+ };
824
+ }
825
+ async getWebhookDeliveries(endpointId, limit) {
826
+ const response = await this.request("webhooks", {
827
+ action: "deliveries",
828
+ endpoint_id: endpointId,
829
+ limit
830
+ });
831
+ return {
832
+ success: response.success,
833
+ data: Array.isArray(response.data) ? response.data.map(mapWebhookDelivery) : []
834
+ };
835
+ }
836
+ async retryWebhookDelivery(deliveryId) {
837
+ const response = await this.request("webhooks", { action: "retry", delivery_id: deliveryId });
838
+ return {
839
+ success: response.success,
840
+ message: typeof response.message === "string" ? response.message : void 0
841
+ };
842
+ }
843
+ async rotateWebhookSecret(endpointId) {
844
+ const response = await this.request("webhooks", {
845
+ action: "rotate_secret",
846
+ endpoint_id: endpointId
847
+ });
848
+ return {
849
+ success: response.success,
850
+ data: {
851
+ secret: typeof response.data?.secret === "string" ? response.data.secret : null
852
+ },
853
+ message: typeof response.message === "string" ? response.message : void 0
854
+ };
855
+ }
856
+ // === BREACH ALERTS ===
857
+ // Configure Slack, email, or webhook notifications for breach risk events.
858
+ // Alerts trigger when project-intent creates projections that exceed cash coverage.
859
+ async listAlerts() {
860
+ const response = await this.request("configure-alerts", { action: "list" });
861
+ return {
862
+ success: response.success,
863
+ data: (response.data || []).map((c) => ({
864
+ id: c.id,
865
+ alertType: c.alert_type,
866
+ channel: c.channel,
867
+ config: c.config,
868
+ thresholds: {
869
+ coverageRatioBelow: c.thresholds?.coverage_ratio_below,
870
+ shortfallAbove: c.thresholds?.shortfall_above
871
+ },
872
+ isActive: c.is_active,
873
+ lastTriggeredAt: c.last_triggered_at,
874
+ triggerCount: c.trigger_count,
875
+ createdAt: c.created_at
876
+ }))
877
+ };
878
+ }
879
+ async createAlert(req) {
880
+ const config = {};
881
+ if ("webhookUrl" in req.config) {
882
+ config.webhook_url = req.config.webhookUrl;
883
+ config.channel = req.config.channel;
884
+ } else if ("recipients" in req.config) {
885
+ config.recipients = req.config.recipients;
886
+ }
887
+ const response = await this.request("configure-alerts", {
888
+ action: "create",
889
+ alert_type: req.alertType,
890
+ channel: req.channel,
891
+ config,
892
+ thresholds: req.thresholds ? {
893
+ coverage_ratio_below: req.thresholds.coverageRatioBelow,
894
+ shortfall_above: req.thresholds.shortfallAbove
895
+ } : void 0,
896
+ is_active: req.isActive
897
+ });
898
+ return {
899
+ success: response.success,
900
+ data: {
901
+ id: response.data.id,
902
+ alertType: response.data.alert_type,
903
+ channel: response.data.channel,
904
+ config: response.data.config || {},
905
+ thresholds: {
906
+ coverageRatioBelow: response.data.thresholds?.coverage_ratio_below,
907
+ shortfallAbove: response.data.thresholds?.shortfall_above
908
+ },
909
+ isActive: response.data.is_active,
910
+ triggerCount: response.data.trigger_count || 0,
911
+ createdAt: response.data.created_at
912
+ }
913
+ };
914
+ }
915
+ async updateAlert(req) {
916
+ const config = req.config ? {} : void 0;
917
+ if (req.config) {
918
+ if ("webhookUrl" in req.config && req.config.webhookUrl) {
919
+ config.webhook_url = req.config.webhookUrl;
920
+ }
921
+ if ("channel" in req.config) {
922
+ config.channel = req.config.channel;
923
+ }
924
+ if ("recipients" in req.config) {
925
+ config.recipients = req.config.recipients;
926
+ }
927
+ }
928
+ const response = await this.request("configure-alerts", {
929
+ action: "update",
930
+ config_id: req.configId,
931
+ config,
932
+ thresholds: req.thresholds ? {
933
+ coverage_ratio_below: req.thresholds.coverageRatioBelow,
934
+ shortfall_above: req.thresholds.shortfallAbove
935
+ } : void 0,
936
+ is_active: req.isActive
937
+ });
938
+ return {
939
+ success: response.success,
940
+ data: {
941
+ id: response.data.id,
942
+ alertType: response.data.alert_type,
943
+ channel: response.data.channel,
944
+ config: response.data.config || {},
945
+ thresholds: {
946
+ coverageRatioBelow: response.data.thresholds?.coverage_ratio_below,
947
+ shortfallAbove: response.data.thresholds?.shortfall_above
948
+ },
949
+ isActive: response.data.is_active,
950
+ triggerCount: response.data.trigger_count ?? 0,
951
+ createdAt: response.data.created_at ?? ""
952
+ }
953
+ };
954
+ }
955
+ async deleteAlert(configId) {
956
+ return this.request("configure-alerts", {
957
+ action: "delete",
958
+ config_id: configId
959
+ });
960
+ }
961
+ async testAlert(configId) {
962
+ return this.request("configure-alerts", {
963
+ action: "test",
964
+ config_id: configId
965
+ });
966
+ }
967
+ // === PREFLIGHT AUTHORIZATION (Phase 3) ===
968
+ // Evaluate whether a proposed transaction should be allowed BEFORE execution.
969
+ // This does NOT move money - only decides if the transaction is permitted.
970
+ async preflightAuthorization(req) {
971
+ const response = await this.request("preflight-authorization", {
972
+ idempotency_key: req.idempotencyKey,
973
+ amount: req.amount,
974
+ currency: req.currency,
975
+ counterparty_name: req.counterpartyName,
976
+ authorizing_instrument_id: req.authorizingInstrumentId,
977
+ expected_date: req.expectedDate,
978
+ category: req.category
979
+ });
980
+ return {
981
+ success: response.success,
982
+ cached: response.cached,
983
+ decision: {
984
+ id: response.decision.id,
985
+ decision: response.decision.decision,
986
+ violatedPolicies: (response.decision.violated_policies || []).map((v) => ({
987
+ policyId: v.policy_id,
988
+ policyType: v.policy_type,
989
+ severity: v.severity,
990
+ reason: v.reason
991
+ })),
992
+ expiresAt: response.decision.expires_at,
993
+ createdAt: response.decision.created_at
994
+ },
995
+ message: response.message
996
+ };
997
+ }
998
+ // Convenience method: preflight check then record expense if allowed
999
+ async preflightAndRecordExpense(preflight, expense) {
1000
+ const preflightResult = await this.preflightAuthorization(preflight);
1001
+ if (preflightResult.decision.decision === "blocked") {
1002
+ return { preflight: preflightResult };
1003
+ }
1004
+ const transaction = await this.recordExpense({
1005
+ ...expense,
1006
+ authorizationDecisionId: preflightResult.decision.id
1007
+ });
1008
+ return { preflight: preflightResult, transaction };
1009
+ }
1010
+ // Convenience method: preflight check then record bill if allowed
1011
+ async preflightAndRecordBill(preflight, bill) {
1012
+ const preflightResult = await this.preflightAuthorization(preflight);
1013
+ if (preflightResult.decision.decision === "blocked") {
1014
+ return { preflight: preflightResult };
1015
+ }
1016
+ const transaction = await this.recordBill({
1017
+ ...bill,
1018
+ authorizationDecisionId: preflightResult.decision.id
1019
+ });
1020
+ return { preflight: preflightResult, transaction };
1021
+ }
1022
+ // === BANK IMPORT ===
1023
+ async getImportTemplates() {
1024
+ return this.request("import-transactions", { action: "get_templates" });
1025
+ }
1026
+ async parseImportFile(fileBase64, format) {
1027
+ return this.request("import-transactions", {
1028
+ action: "parse_preview",
1029
+ data: fileBase64,
1030
+ format
1031
+ });
1032
+ }
1033
+ async importTransactions(transactions) {
1034
+ return this.request("import-transactions", {
1035
+ action: "import",
1036
+ transactions
1037
+ });
1038
+ }
1039
+ async saveImportTemplate(template) {
1040
+ return this.request("import-transactions", {
1041
+ action: "save_template",
1042
+ template
1043
+ });
1044
+ }
1045
+ // === ESCROW / HELD FUNDS ===
1046
+ async getEscrowSummary() {
1047
+ const response = await this.requestGet("holds/summary");
1048
+ return {
1049
+ success: response.success,
1050
+ summary: response.summary || {}
1051
+ };
1052
+ }
1053
+ async getHeldFunds(options) {
1054
+ return this.requestGet("holds", {
1055
+ venture_id: options?.ventureId,
1056
+ participant_id: options?.creatorId,
1057
+ ready_only: options?.readyOnly,
1058
+ limit: options?.limit
1059
+ });
1060
+ }
1061
+ async releaseFunds(entryId, executeTransfer = true) {
1062
+ const response = await this.request(`holds/${entryId}/release`, {
1063
+ execute_transfer: executeTransfer
1064
+ });
1065
+ return {
1066
+ success: response.success,
1067
+ release_id: response.release?.id ?? null,
1068
+ entry_id: response.release?.hold_id ?? entryId,
1069
+ executed: Boolean(response.release?.executed),
1070
+ transfer_id: response.release?.transfer_id ?? null,
1071
+ transfer_status: response.release?.transfer_status ?? null,
1072
+ amount: response.release?.amount ?? null,
1073
+ currency: response.release?.currency ?? null
1074
+ };
1075
+ }
1076
+ // === PAYOUT ELIGIBILITY ===
1077
+ async checkPayoutEligibility(participantId) {
1078
+ const response = await this.requestGet(`participants/${participantId}/payout-eligibility`);
1079
+ return {
1080
+ success: response.success,
1081
+ participant_id: response.eligibility?.participant_id ?? participantId,
1082
+ eligible: Boolean(response.eligibility?.eligible),
1083
+ available_balance: response.eligibility?.available_balance ?? 0,
1084
+ issues: response.eligibility?.issues || [],
1085
+ requirements: response.eligibility?.requirements || {}
1086
+ };
1087
+ }
1088
+ // === HEALTH CHECKS ===
1089
+ async runHealthCheck() {
1090
+ return this.request("health-check", { action: "run" });
1091
+ }
1092
+ async getHealthStatus() {
1093
+ return this.request("health-check", { action: "status" });
1094
+ }
1095
+ async getHealthHistory() {
1096
+ return this.request("health-check", { action: "history" });
1097
+ }
1098
+ // === FINANCIAL REPORTS (DETAILED) ===
1099
+ async getAPAging(asOfDate) {
1100
+ return this.requestGet("ap-aging", { as_of_date: asOfDate });
1101
+ }
1102
+ async getARAging(asOfDate) {
1103
+ return this.requestGet("ar-aging", { as_of_date: asOfDate });
1104
+ }
1105
+ async getBalanceSheet(asOfDate) {
1106
+ return this.requestGet("balance-sheet", { as_of_date: asOfDate });
1107
+ }
1108
+ async getDetailedTrialBalance(options) {
1109
+ return this.requestGet("trial-balance", {
1110
+ as_of: options?.asOf,
1111
+ snapshot: options?.snapshot ? "true" : void 0
1112
+ });
1113
+ }
1114
+ async getDetailedProfitLoss(options) {
1115
+ return this.requestGet("profit-loss", {
1116
+ year: options?.year,
1117
+ month: options?.month,
1118
+ quarter: options?.quarter,
1119
+ start_date: options?.startDate,
1120
+ end_date: options?.endDate,
1121
+ breakdown: options?.breakdown
1122
+ });
1123
+ }
1124
+ async getRunway() {
1125
+ return this.requestGet("get-runway");
1126
+ }
1127
+ // === TREASURY RESOURCES ===
1128
+ async createParticipant(req) {
1129
+ const response = await this.request("participants", {
1130
+ participant_id: req.participantId,
1131
+ user_id: req.userId,
1132
+ display_name: req.displayName,
1133
+ email: req.email,
1134
+ default_split_percent: req.defaultSplitPercent,
1135
+ tax_info: req.taxInfo ? {
1136
+ tax_id_type: req.taxInfo.taxIdType,
1137
+ tax_id_last4: req.taxInfo.taxIdLast4,
1138
+ legal_name: req.taxInfo.legalName,
1139
+ business_type: req.taxInfo.businessType,
1140
+ address: req.taxInfo.address ? {
1141
+ line1: req.taxInfo.address.line1,
1142
+ line2: req.taxInfo.address.line2,
1143
+ city: req.taxInfo.address.city,
1144
+ state: req.taxInfo.address.state,
1145
+ postal_code: req.taxInfo.address.postalCode,
1146
+ country: req.taxInfo.address.country
1147
+ } : void 0
1148
+ } : void 0,
1149
+ payout_preferences: req.payoutPreferences ? {
1150
+ schedule: req.payoutPreferences.schedule,
1151
+ minimum_amount: req.payoutPreferences.minimumAmount,
1152
+ method: req.payoutPreferences.method
1153
+ } : void 0,
1154
+ metadata: req.metadata
1155
+ });
1156
+ const participant = response.participant || {};
1157
+ return {
1158
+ success: response.success,
1159
+ participant: {
1160
+ id: participant.id,
1161
+ accountId: participant.account_id,
1162
+ linkedUserId: participant.linked_user_id ?? null,
1163
+ displayName: participant.display_name,
1164
+ email: participant.email,
1165
+ defaultSplitPercent: participant.default_split_percent,
1166
+ payoutPreferences: participant.payout_preferences || {},
1167
+ createdAt: participant.created_at
1168
+ }
1169
+ };
1170
+ }
1171
+ async listParticipants() {
1172
+ const response = await this.requestGet("participants");
1173
+ return {
1174
+ success: response.success,
1175
+ participants: (response.participants || []).map((participant) => ({
1176
+ id: participant.id,
1177
+ linkedUserId: participant.linked_user_id ?? null,
1178
+ name: participant.name ?? null,
1179
+ tier: participant.tier ?? null,
1180
+ ledgerBalance: participant.ledger_balance,
1181
+ heldAmount: participant.held_amount,
1182
+ availableBalance: participant.available_balance
1183
+ }))
1184
+ };
1185
+ }
1186
+ async getParticipant(participantId) {
1187
+ const response = await this.requestGet(`participants/${participantId}`);
1188
+ const participant = response.participant || {};
1189
+ return {
1190
+ success: response.success,
1191
+ participant: {
1192
+ id: participant.id,
1193
+ linkedUserId: participant.linked_user_id ?? null,
1194
+ name: participant.name ?? null,
1195
+ tier: participant.tier ?? null,
1196
+ customSplitPercent: participant.custom_split_percent ?? null,
1197
+ ledgerBalance: participant.ledger_balance,
1198
+ heldAmount: participant.held_amount,
1199
+ availableBalance: participant.available_balance,
1200
+ holds: (participant.holds || []).map((hold) => ({
1201
+ amount: hold.amount,
1202
+ reason: hold.reason ?? null,
1203
+ releaseDate: hold.release_date ?? null,
1204
+ status: hold.status
1205
+ }))
1206
+ }
1207
+ };
1208
+ }
1209
+ async getParticipantPayoutEligibility(participantId) {
1210
+ const response = await this.requestGet(`participants/${participantId}/payout-eligibility`);
1211
+ return {
1212
+ success: response.success,
1213
+ eligibility: {
1214
+ participantId: response.eligibility?.participant_id ?? participantId,
1215
+ eligible: Boolean(response.eligibility?.eligible),
1216
+ availableBalance: response.eligibility?.available_balance ?? 0,
1217
+ issues: response.eligibility?.issues || [],
1218
+ requirements: response.eligibility?.requirements || {}
1219
+ }
1220
+ };
1221
+ }
1222
+ // === LEDGER MANAGEMENT ===
1223
+ async createLedger(req) {
1224
+ const response = await this.request("create-ledger", {
1225
+ business_name: req.businessName,
1226
+ owner_email: req.ownerEmail,
1227
+ ledger_mode: req.ledgerMode,
1228
+ settings: req.settings ? {
1229
+ default_tax_rate: req.settings.defaultTaxRate,
1230
+ default_split_percent: req.settings.defaultSplitPercent,
1231
+ platform_fee_percent: req.settings.platformFeePercent,
1232
+ min_payout_amount: req.settings.minPayoutAmount,
1233
+ payout_schedule: req.settings.payoutSchedule,
1234
+ tax_withholding_percent: req.settings.taxWithholdingPercent,
1235
+ currency: req.settings.currency,
1236
+ fiscal_year_start: req.settings.fiscalYearStart,
1237
+ receipt_threshold: req.settings.receiptThreshold
1238
+ } : void 0
1239
+ });
1240
+ return {
1241
+ success: response.success,
1242
+ ledger: {
1243
+ id: response.ledger.id,
1244
+ businessName: response.ledger.business_name,
1245
+ ledgerMode: response.ledger.ledger_mode,
1246
+ apiKey: response.ledger.api_key,
1247
+ status: response.ledger.status,
1248
+ createdAt: response.ledger.created_at
1249
+ },
1250
+ warning: response.warning
1251
+ };
1252
+ }
1253
+ // === ACCOUNTING ADJUSTMENTS ===
1254
+ async recordAdjustment(req) {
1255
+ return this.request("record-adjustment", {
1256
+ adjustment_type: req.adjustmentType,
1257
+ adjustment_date: req.adjustmentDate,
1258
+ entries: req.entries.map((e) => ({
1259
+ account_type: e.accountType,
1260
+ entity_id: e.entityId,
1261
+ entry_type: e.entryType,
1262
+ amount: e.amount
1263
+ })),
1264
+ reason: req.reason,
1265
+ original_transaction_id: req.originalTransactionId,
1266
+ supporting_documentation: req.supportingDocumentation,
1267
+ prepared_by: req.preparedBy
1268
+ });
1269
+ }
1270
+ async recordOpeningBalance(req) {
1271
+ return this.request("record-opening-balance", {
1272
+ as_of_date: req.asOfDate,
1273
+ source: req.source,
1274
+ source_description: req.sourceDescription,
1275
+ balances: req.balances.map((b) => ({
1276
+ account_type: b.accountType,
1277
+ entity_id: b.entityId,
1278
+ balance: b.balance
1279
+ }))
1280
+ });
1281
+ }
1282
+ async recordTransfer(req) {
1283
+ return this.request("record-transfer", {
1284
+ from_account_type: req.fromAccountType,
1285
+ to_account_type: req.toAccountType,
1286
+ amount: req.amount,
1287
+ transfer_type: req.transferType,
1288
+ description: req.description,
1289
+ reference_id: req.referenceId
1290
+ });
1291
+ }
1292
+ // === RISK & POLICY ===
1293
+ async evaluateFraud(req) {
1294
+ const response = await this.request("fraud/evaluations", {
1295
+ idempotency_key: req.idempotencyKey,
1296
+ amount: req.amount,
1297
+ currency: req.currency,
1298
+ counterparty_name: req.counterpartyName,
1299
+ authorizing_instrument_id: req.authorizingInstrumentId,
1300
+ expected_date: req.expectedDate,
1301
+ category: req.category
1302
+ });
1303
+ return {
1304
+ success: response.success,
1305
+ cached: response.cached,
1306
+ evaluation: {
1307
+ id: response.evaluation.id,
1308
+ signal: response.evaluation.signal,
1309
+ riskFactors: (response.evaluation.risk_factors || []).map((f) => ({
1310
+ policyId: f.policy_id,
1311
+ policyType: f.policy_type,
1312
+ severity: f.severity,
1313
+ indicator: f.indicator
1314
+ })),
1315
+ validUntil: response.evaluation.valid_until,
1316
+ createdAt: response.evaluation.created_at,
1317
+ acknowledgedAt: response.evaluation.acknowledged_at
1318
+ }
1319
+ };
1320
+ }
1321
+ async createFraudPolicy(req) {
1322
+ const response = await this.request("fraud/policies", {
1323
+ policy_type: req.policyType,
1324
+ config: req.config,
1325
+ severity: req.severity,
1326
+ priority: req.priority
1327
+ });
1328
+ return {
1329
+ success: response.success,
1330
+ policy: {
1331
+ id: response.policy.id,
1332
+ type: response.policy.type,
1333
+ severity: response.policy.severity,
1334
+ priority: response.policy.priority,
1335
+ isActive: Boolean(response.policy.is_active),
1336
+ config: response.policy.config || {},
1337
+ createdAt: response.policy.created_at ?? null,
1338
+ updatedAt: response.policy.updated_at ?? null
1339
+ }
1340
+ };
1341
+ }
1342
+ async listFraudPolicies() {
1343
+ const response = await this.requestGet("fraud/policies");
1344
+ return {
1345
+ success: response.success,
1346
+ policies: (response.policies || []).map((policy) => ({
1347
+ id: policy.id,
1348
+ type: policy.type,
1349
+ severity: policy.severity,
1350
+ priority: policy.priority,
1351
+ isActive: Boolean(policy.is_active),
1352
+ config: policy.config || {},
1353
+ createdAt: policy.created_at ?? null,
1354
+ updatedAt: policy.updated_at ?? null
1355
+ }))
1356
+ };
1357
+ }
1358
+ async deleteFraudPolicy(policyId) {
1359
+ const response = await this.requestDelete(`fraud/policies/${policyId}`);
1360
+ return {
1361
+ success: response.success,
1362
+ deleted: Boolean(response.deleted),
1363
+ policyId: response.policy_id
1364
+ };
1365
+ }
1366
+ // === TAX DOCUMENTS ===
1367
+ async calculateTaxForParticipant(participantId, taxYear) {
1368
+ const response = await this.requestGet(`tax/calculations/${participantId}`, {
1369
+ tax_year: taxYear
1370
+ });
1371
+ return {
1372
+ success: response.success,
1373
+ calculation: {
1374
+ participantId: response.calculation.participant_id,
1375
+ taxYear: response.calculation.tax_year,
1376
+ grossPayments: response.calculation.gross_payments,
1377
+ transactionCount: response.calculation.transaction_count,
1378
+ requires1099: Boolean(response.calculation.requires_1099),
1379
+ monthlyTotals: response.calculation.monthly_totals || {},
1380
+ threshold: response.calculation.threshold,
1381
+ linkedUserId: response.calculation.linked_user_id ?? null,
1382
+ sharedTaxProfile: response.calculation.shared_tax_profile ? {
1383
+ status: response.calculation.shared_tax_profile.status,
1384
+ legalName: response.calculation.shared_tax_profile.legal_name ?? null,
1385
+ taxIdLast4: response.calculation.shared_tax_profile.tax_id_last4 ?? null
1386
+ } : null
1387
+ }
1388
+ };
1389
+ }
1390
+ async generateAllTaxDocuments(taxYear) {
1391
+ const response = await this.request("tax/documents/generate", { tax_year: taxYear });
1392
+ return {
1393
+ success: response.success,
1394
+ generation: {
1395
+ taxYear: response.generation.tax_year,
1396
+ created: response.generation.created,
1397
+ skipped: response.generation.skipped,
1398
+ totalAmount: response.generation.total_amount
1399
+ }
1400
+ };
1401
+ }
1402
+ async listTaxDocuments(taxYear) {
1403
+ const response = await this.requestGet("tax/documents", { tax_year: taxYear });
1404
+ return {
1405
+ success: response.success,
1406
+ taxYear: response.tax_year,
1407
+ summary: {
1408
+ totalDocuments: response.summary?.total_documents ?? 0,
1409
+ totalAmount: response.summary?.total_amount ?? 0,
1410
+ byStatus: {
1411
+ calculated: response.summary?.by_status?.calculated ?? 0,
1412
+ exported: response.summary?.by_status?.exported ?? 0,
1413
+ filed: response.summary?.by_status?.filed ?? 0
1414
+ }
1415
+ },
1416
+ documents: response.documents || []
1417
+ };
1418
+ }
1419
+ async getTaxDocument(documentId) {
1420
+ const response = await this.requestGet(`tax/documents/${documentId}`);
1421
+ return {
1422
+ success: response.success,
1423
+ document: response.document
1424
+ };
1425
+ }
1426
+ async exportTaxDocuments(taxYear, format = "json") {
1427
+ if (format === "csv") {
1428
+ const response = await this.requestGetRaw("tax/documents/export", { tax_year: taxYear, format });
1429
+ const csv = await response.text();
1430
+ const disposition = response.headers.get("Content-Disposition") || "";
1431
+ const filenameMatch = disposition.match(/filename="?([^"]+)"?/);
1432
+ return { csv, filename: filenameMatch?.[1] || `1099_export_${taxYear}.csv` };
1433
+ }
1434
+ return this.requestGet("tax/documents/export", { tax_year: taxYear, format });
1435
+ }
1436
+ async markTaxDocumentFiled(documentId) {
1437
+ const response = await this.request(`tax/documents/${documentId}/mark-filed`, {});
1438
+ return {
1439
+ success: response.success,
1440
+ document: {
1441
+ id: response.document.id,
1442
+ tax_year: response.document.tax_year,
1443
+ status: response.document.status
1444
+ }
1445
+ };
1446
+ }
1447
+ async generateTaxSummary(taxYear, creatorId) {
1448
+ const response = await this.requestGet(`tax/summaries/${taxYear}`, {
1449
+ participant_id: creatorId
1450
+ });
1451
+ return {
1452
+ success: response.success,
1453
+ taxYear: response.tax_year,
1454
+ note: response.note,
1455
+ summaries: (response.summaries || []).map((summary) => ({
1456
+ participantId: summary.participant_id,
1457
+ linkedUserId: summary.linked_user_id ?? null,
1458
+ grossEarnings: summary.gross_earnings,
1459
+ refundsIssued: summary.refunds_issued,
1460
+ netEarnings: summary.net_earnings,
1461
+ totalPaidOut: summary.total_paid_out,
1462
+ requires1099: Boolean(summary.requires_1099),
1463
+ sharedTaxProfile: summary.shared_tax_profile ? {
1464
+ status: summary.shared_tax_profile.status,
1465
+ legalName: summary.shared_tax_profile.legal_name ?? null,
1466
+ taxIdLast4: summary.shared_tax_profile.tax_id_last4 ?? null
1467
+ } : null
1468
+ })),
1469
+ totals: {
1470
+ totalGross: response.totals.total_gross,
1471
+ totalRefunds: response.totals.total_refunds,
1472
+ totalNet: response.totals.total_net,
1473
+ totalPaid: response.totals.total_paid,
1474
+ participantsRequiring1099: response.totals.participants_requiring_1099
1475
+ }
1476
+ };
1477
+ }
1478
+ async markTaxDocumentsFiledBulk(taxYear) {
1479
+ return this.request("tax/documents/mark-filed", { tax_year: taxYear });
1480
+ }
1481
+ async correctTaxDocument(documentId, params) {
1482
+ return this.request(`tax/documents/${documentId}/correct`, {
1483
+ reason: params.reason,
1484
+ gross_amount: params.grossAmount,
1485
+ federal_withholding: params.federalWithholding,
1486
+ state_withholding: params.stateWithholding
1487
+ });
1488
+ }
1489
+ async deliverTaxDocumentCopyB(taxYear) {
1490
+ return this.request("tax/documents/deliver-copy-b", { tax_year: taxYear });
1491
+ }
1492
+ async generateTaxDocumentPdf(documentId, copyType) {
1493
+ return this.request(`tax/documents/${documentId}/pdf`, {
1494
+ copy_type: copyType
1495
+ });
1496
+ }
1497
+ async generateTaxDocumentPdfBatch(taxYear, copyType) {
1498
+ return this.request("tax/documents/pdf/batch", {
1499
+ tax_year: taxYear,
1500
+ copy_type: copyType
1501
+ });
1502
+ }
1503
+ // === COMPLIANCE MONITORING ===
1504
+ async getComplianceOverview(options) {
1505
+ const response = await this.requestGet("compliance/overview", {
1506
+ days: options?.days,
1507
+ hours: options?.hours
1508
+ });
1509
+ return {
1510
+ success: response.success,
1511
+ overview: {
1512
+ windowDays: response.overview.window_days,
1513
+ accessWindowHours: response.overview.access_window_hours,
1514
+ totalEvents: response.overview.total_events,
1515
+ uniqueIps: response.overview.unique_ips,
1516
+ uniqueActors: response.overview.unique_actors,
1517
+ highRiskEvents: response.overview.high_risk_events,
1518
+ criticalRiskEvents: response.overview.critical_risk_events,
1519
+ failedAuthEvents: response.overview.failed_auth_events,
1520
+ payoutsFailed: response.overview.payouts_failed,
1521
+ refundsRecorded: response.overview.refunds_recorded,
1522
+ disputeEvents: response.overview.dispute_events
1523
+ },
1524
+ note: response.note
1525
+ };
1526
+ }
1527
+ async listComplianceAccessPatterns(options) {
1528
+ const response = await this.requestGet("compliance/access-patterns", {
1529
+ hours: options?.hours,
1530
+ limit: options?.limit
1531
+ });
1532
+ return {
1533
+ success: response.success,
1534
+ windowHours: response.window_hours,
1535
+ count: response.count,
1536
+ patterns: (response.patterns || []).map((pattern) => ({
1537
+ ipAddress: pattern.ip_address,
1538
+ hour: pattern.hour,
1539
+ requestCount: pattern.request_count,
1540
+ uniqueActions: pattern.unique_actions,
1541
+ actions: pattern.actions || [],
1542
+ maxRiskScore: pattern.max_risk_score,
1543
+ failedAuths: pattern.failed_auths
1544
+ }))
1545
+ };
1546
+ }
1547
+ async listComplianceFinancialActivity(options) {
1548
+ const response = await this.requestGet("compliance/financial-activity", {
1549
+ days: options?.days
1550
+ });
1551
+ return {
1552
+ success: response.success,
1553
+ windowDays: response.window_days,
1554
+ activity: (response.activity || []).map((entry) => ({
1555
+ date: entry.date,
1556
+ payoutsInitiated: entry.payouts_initiated,
1557
+ payoutsCompleted: entry.payouts_completed,
1558
+ payoutsFailed: entry.payouts_failed,
1559
+ salesRecorded: entry.sales_recorded,
1560
+ refundsRecorded: entry.refunds_recorded,
1561
+ disputeEvents: entry.dispute_events
1562
+ }))
1563
+ };
1564
+ }
1565
+ async listComplianceSecuritySummary(options) {
1566
+ const response = await this.requestGet("compliance/security-summary", {
1567
+ days: options?.days
1568
+ });
1569
+ return {
1570
+ success: response.success,
1571
+ windowDays: response.window_days,
1572
+ summary: (response.summary || []).map((entry) => ({
1573
+ date: entry.date,
1574
+ action: entry.action,
1575
+ eventCount: entry.event_count,
1576
+ uniqueIps: entry.unique_ips,
1577
+ uniqueActors: entry.unique_actors,
1578
+ avgRiskScore: entry.avg_risk_score,
1579
+ maxRiskScore: entry.max_risk_score,
1580
+ highRiskCount: entry.high_risk_count,
1581
+ criticalRiskCount: entry.critical_risk_count
1582
+ }))
1583
+ };
1584
+ }
1585
+ async exportReport(req) {
1586
+ const body = {
1587
+ report_type: req.reportType,
1588
+ format: req.format,
1589
+ start_date: req.startDate,
1590
+ end_date: req.endDate,
1591
+ creator_id: req.creatorId
1592
+ };
1593
+ if (req.format === "csv") {
1594
+ const response = await this.requestRaw("export-report", body);
1595
+ const csv = await response.text();
1596
+ const disposition = response.headers.get("Content-Disposition") || "";
1597
+ const filenameMatch = disposition.match(/filename="?([^"]+)"?/);
1598
+ return { csv, filename: filenameMatch?.[1] || `${req.reportType}.csv` };
1599
+ }
1600
+ return this.request("export-report", body);
1601
+ }
1602
+ // === RECEIPTS ===
1603
+ async uploadReceipt(req) {
1604
+ return this.request("upload-receipt", {
1605
+ file_url: req.fileUrl,
1606
+ file_name: req.fileName,
1607
+ file_size: req.fileSize,
1608
+ mime_type: req.mimeType,
1609
+ merchant_name: req.merchantName,
1610
+ transaction_date: req.transactionDate,
1611
+ total_amount: req.totalAmount,
1612
+ transaction_id: req.transactionId
1613
+ });
1614
+ }
1615
+ // === PAYMENTS ===
1616
+ async receivePayment(req) {
1617
+ return this.request("receive-payment", {
1618
+ amount: req.amount,
1619
+ invoice_transaction_id: req.invoiceTransactionId,
1620
+ customer_name: req.customerName,
1621
+ customer_id: req.customerId,
1622
+ reference_id: req.referenceId,
1623
+ payment_method: req.paymentMethod,
1624
+ payment_date: req.paymentDate,
1625
+ metadata: req.metadata
1626
+ });
1627
+ }
1628
+ // === BREACH ALERTS ===
1629
+ async sendBreachAlert(req) {
1630
+ const response = await this.request("send-breach-alert", {
1631
+ cash_balance: req.cashBalance,
1632
+ pending_total: req.pendingTotal,
1633
+ shortfall: req.shortfall,
1634
+ coverage_ratio: req.coverageRatio,
1635
+ triggered_by: req.triggeredBy,
1636
+ instrument_id: req.instrumentId,
1637
+ external_ref: req.externalRef,
1638
+ projections_created: req.projectionsCreated,
1639
+ channel: req.channel
1640
+ });
1641
+ return {
1642
+ success: response.success,
1643
+ message: response.message,
1644
+ alertsSent: response.alerts_sent ?? 0,
1645
+ alertsFailed: response.alerts_failed,
1646
+ alertsSkipped: response.alerts_skipped,
1647
+ results: response.results ? response.results.map((r) => ({
1648
+ channel: r.channel,
1649
+ success: r.success,
1650
+ error: r.error
1651
+ })) : void 0
1652
+ };
1653
+ }
1654
+ // === WALLETS ===
1655
+ mapWalletObject(wallet) {
1656
+ return {
1657
+ id: wallet.id,
1658
+ object: "wallet",
1659
+ walletType: wallet.wallet_type,
1660
+ scopeType: wallet.scope_type,
1661
+ ownerId: wallet.owner_id ?? null,
1662
+ ownerType: wallet.owner_type ?? null,
1663
+ participantId: wallet.participant_id ?? null,
1664
+ accountType: wallet.account_type,
1665
+ name: wallet.name ?? null,
1666
+ currency: wallet.currency,
1667
+ status: wallet.status,
1668
+ balance: wallet.balance,
1669
+ heldAmount: wallet.held_amount ?? 0,
1670
+ availableBalance: wallet.available_balance ?? wallet.balance,
1671
+ redeemable: wallet.redeemable === true,
1672
+ transferable: wallet.transferable === true,
1673
+ topupSupported: wallet.topup_supported === true,
1674
+ payoutSupported: wallet.payout_supported === true,
1675
+ createdAt: wallet.created_at ?? null,
1676
+ metadata: wallet.metadata || {}
1677
+ };
1678
+ }
1679
+ async listWallets(filters = {}) {
1680
+ const response = await this.requestGet("wallets", {
1681
+ owner_id: filters.ownerId,
1682
+ owner_type: filters.ownerType,
1683
+ wallet_type: filters.walletType,
1684
+ limit: filters.limit,
1685
+ offset: filters.offset
1686
+ });
1687
+ return {
1688
+ success: response.success,
1689
+ wallets: (response.wallets || []).map((wallet) => this.mapWalletObject(wallet)),
1690
+ total: response.total,
1691
+ limit: response.limit,
1692
+ offset: response.offset
1693
+ };
1694
+ }
1695
+ async createWallet(req) {
1696
+ const response = await this.request("wallets", {
1697
+ owner_id: req.ownerId,
1698
+ participant_id: req.participantId,
1699
+ owner_type: req.ownerType,
1700
+ wallet_type: req.walletType,
1701
+ name: req.name,
1702
+ metadata: req.metadata
1703
+ });
1704
+ return {
1705
+ success: response.success,
1706
+ created: response.created === true,
1707
+ wallet: this.mapWalletObject(response.wallet)
1708
+ };
1709
+ }
1710
+ async getWallet(walletId) {
1711
+ const response = await this.requestGet(`wallets/${walletId}`);
1712
+ return {
1713
+ success: response.success,
1714
+ wallet: this.mapWalletObject(response.wallet)
1715
+ };
1716
+ }
1717
+ async getWalletEntries(walletId, options) {
1718
+ const response = await this.requestGet(`wallets/${walletId}/entries`, {
1719
+ limit: options?.limit,
1720
+ offset: options?.offset
1721
+ });
1722
+ return {
1723
+ success: response.success,
1724
+ wallet: response.wallet ? this.mapWalletObject(response.wallet) : null,
1725
+ entries: (response.entries || []).map((t) => ({
1726
+ entryId: t.entry_id,
1727
+ entryType: t.entry_type,
1728
+ amount: t.amount,
1729
+ transactionId: t.transaction_id,
1730
+ referenceId: t.reference_id,
1731
+ transactionType: t.transaction_type,
1732
+ description: t.description,
1733
+ status: t.status,
1734
+ metadata: t.metadata,
1735
+ createdAt: t.created_at
1736
+ })),
1737
+ total: response.total,
1738
+ limit: response.limit,
1739
+ offset: response.offset
1740
+ };
1741
+ }
1742
+ async topUpWallet(req) {
1743
+ const response = await this.request(`wallets/${req.walletId}/topups`, {
1744
+ amount: req.amount,
1745
+ reference_id: req.referenceId,
1746
+ description: req.description,
1747
+ metadata: req.metadata
1748
+ });
1749
+ const topup = response.topup || response.deposit || response;
1750
+ return {
1751
+ success: response.success,
1752
+ walletId: topup.wallet_id ?? null,
1753
+ ownerId: topup.owner_id ?? null,
1754
+ transactionId: topup.transaction_id ?? null,
1755
+ balance: topup.balance ?? null
1756
+ };
1757
+ }
1758
+ async withdrawFromWallet(req) {
1759
+ const response = await this.request(`wallets/${req.walletId}/withdrawals`, {
1760
+ amount: req.amount,
1761
+ reference_id: req.referenceId,
1762
+ description: req.description,
1763
+ metadata: req.metadata
1764
+ });
1765
+ const withdrawal = response.withdrawal || response;
1766
+ return {
1767
+ success: response.success,
1768
+ walletId: withdrawal.wallet_id ?? null,
1769
+ ownerId: withdrawal.owner_id ?? null,
1770
+ transactionId: withdrawal.transaction_id ?? null,
1771
+ balance: withdrawal.balance ?? null
1772
+ };
1773
+ }
1774
+ async createTransfer(req) {
1775
+ const response = await this.request("transfers", {
1776
+ from_participant_id: req.fromParticipantId,
1777
+ to_participant_id: req.toParticipantId,
1778
+ amount: req.amount,
1779
+ reference_id: req.referenceId,
1780
+ description: req.description,
1781
+ metadata: req.metadata
1782
+ });
1783
+ const transfer = response.transfer || response;
1784
+ return {
1785
+ success: response.success,
1786
+ transfer: {
1787
+ transactionId: transfer.transaction_id,
1788
+ fromParticipantId: req.fromParticipantId,
1789
+ toParticipantId: req.toParticipantId,
1790
+ fromBalance: transfer.from_balance,
1791
+ toBalance: transfer.to_balance
1792
+ }
1793
+ };
1794
+ }
1795
+ async listHolds(options) {
1796
+ const response = await this.requestGet("holds", {
1797
+ participant_id: options?.participantId,
1798
+ venture_id: options?.ventureId,
1799
+ ready_only: options?.readyOnly,
1800
+ limit: options?.limit
1801
+ });
1802
+ return {
1803
+ success: response.success,
1804
+ holds: (response.holds || []).map((hold) => ({
1805
+ id: hold.id,
1806
+ participantId: hold.participant_id ?? null,
1807
+ participantName: hold.participant_name ?? null,
1808
+ amount: hold.amount,
1809
+ currency: hold.currency,
1810
+ heldSince: hold.held_since,
1811
+ daysHeld: hold.days_held,
1812
+ holdReason: hold.hold_reason ?? null,
1813
+ holdUntil: hold.hold_until ?? null,
1814
+ readyForRelease: Boolean(hold.ready_for_release),
1815
+ releaseStatus: hold.release_status,
1816
+ transactionReference: hold.transaction_reference ?? null,
1817
+ productName: hold.product_name ?? null,
1818
+ ventureId: hold.venture_id ?? null,
1819
+ connectedAccountReady: Boolean(hold.connected_account_ready)
1820
+ })),
1821
+ count: response.count ?? 0
1822
+ };
1823
+ }
1824
+ async getHoldSummary() {
1825
+ const response = await this.requestGet("holds/summary");
1826
+ return {
1827
+ success: response.success,
1828
+ summary: response.summary || {}
1829
+ };
1830
+ }
1831
+ async releaseHold(req) {
1832
+ const response = await this.request(`holds/${req.holdId}/release`, {
1833
+ execute_transfer: req.executeTransfer !== false
1834
+ });
1835
+ const release = response.release || response;
1836
+ return {
1837
+ success: response.success,
1838
+ release: {
1839
+ id: release.id,
1840
+ holdId: release.hold_id ?? req.holdId,
1841
+ executed: Boolean(release.executed),
1842
+ transferId: release.transfer_id ?? null,
1843
+ transferStatus: release.transfer_status ?? null,
1844
+ amount: release.amount ?? null,
1845
+ currency: release.currency ?? null
1846
+ }
1847
+ };
1848
+ }
1849
+ async createCheckoutSession(req) {
1850
+ const hasPaymentMethod = "paymentMethodId" in req ? Boolean(req.paymentMethodId || req.sourceId) : false;
1851
+ if (!hasPaymentMethod && !req.successUrl) {
1852
+ throw new Error("Either paymentMethodId/sourceId or successUrl is required");
1853
+ }
1854
+ const response = await this.request("checkout-sessions", {
1855
+ amount: req.amount,
1856
+ participant_id: req.participantId,
1857
+ currency: req.currency,
1858
+ product_id: req.productId,
1859
+ product_name: req.productName,
1860
+ customer_email: req.customerEmail,
1861
+ customer_id: req.customerId,
1862
+ payment_method_id: "paymentMethodId" in req ? req.paymentMethodId : void 0,
1863
+ source_id: "sourceId" in req ? req.sourceId : void 0,
1864
+ success_url: req.successUrl,
1865
+ cancel_url: req.cancelUrl,
1866
+ idempotency_key: "idempotencyKey" in req ? req.idempotencyKey : void 0,
1867
+ metadata: req.metadata
1868
+ });
1869
+ const checkoutSession = response.checkout_session || response;
1870
+ return {
1871
+ success: Boolean(response.success),
1872
+ checkoutSession: {
1873
+ id: checkoutSession.id ?? checkoutSession.payment_id ?? checkoutSession.payment_intent_id,
1874
+ mode: checkoutSession.mode === "session" ? "session" : "direct",
1875
+ checkoutUrl: checkoutSession.checkout_url ?? null,
1876
+ paymentId: checkoutSession.payment_id ?? null,
1877
+ paymentIntentId: checkoutSession.payment_intent_id ?? checkoutSession.payment_id ?? null,
1878
+ status: checkoutSession.status ?? null,
1879
+ requiresAction: Boolean(checkoutSession.requires_action),
1880
+ amount: checkoutSession.amount ?? req.amount,
1881
+ currency: checkoutSession.currency ?? (req.currency || "USD"),
1882
+ expiresAt: checkoutSession.expires_at ?? null,
1883
+ fundingTransactionId: checkoutSession.funding_transaction_id ?? null,
1884
+ saleTransactionId: checkoutSession.sale_transaction_id ?? null,
1885
+ saleReference: checkoutSession.sale_reference ?? null,
1886
+ breakdown: checkoutSession.breakdown ? {
1887
+ grossAmount: checkoutSession.breakdown.gross_amount,
1888
+ creatorAmount: checkoutSession.breakdown.creator_amount,
1889
+ platformAmount: checkoutSession.breakdown.platform_amount,
1890
+ creatorPercent: checkoutSession.breakdown.creator_percent
1891
+ } : null
1892
+ }
1893
+ };
1894
+ }
1895
+ async createPayout(req) {
1896
+ const response = await this.request("payouts", {
1897
+ participant_id: req.participantId,
1898
+ wallet_id: req.walletId,
1899
+ amount: req.amount,
1900
+ reference_id: req.referenceId,
1901
+ reference_type: req.referenceType,
1902
+ description: req.description,
1903
+ payout_method: req.payoutMethod,
1904
+ fees: req.fees,
1905
+ fees_paid_by: req.feesPaidBy,
1906
+ metadata: req.metadata
1907
+ });
1908
+ const payout = response.payout || response;
1909
+ return {
1910
+ success: response.success,
1911
+ payout: {
1912
+ id: payout.id,
1913
+ transactionId: payout.transaction_id,
1914
+ grossAmount: payout.gross_amount ?? null,
1915
+ fees: payout.fees ?? null,
1916
+ netAmount: payout.net_amount ?? null,
1917
+ previousBalance: payout.previous_balance ?? null,
1918
+ newBalance: payout.new_balance ?? null
1919
+ }
1920
+ };
1921
+ }
1922
+ async createRefund(req) {
1923
+ const response = await this.request("refunds", {
1924
+ sale_reference: req.saleReference,
1925
+ reason: req.reason,
1926
+ amount: req.amount,
1927
+ refund_from: req.refundFrom,
1928
+ external_refund_id: req.externalRefundId,
1929
+ idempotency_key: req.idempotencyKey,
1930
+ metadata: req.metadata
1931
+ });
1932
+ const refund = response.refund || response;
1933
+ return {
1934
+ success: response.success,
1935
+ warning: response.warning ?? null,
1936
+ warningCode: response.warning_code ?? null,
1937
+ refund: {
1938
+ id: refund.id ?? refund.reference_id ?? refund.transaction_id ?? "",
1939
+ transactionId: refund.transaction_id ?? null,
1940
+ referenceId: refund.reference_id ?? null,
1941
+ saleReference: refund.sale_reference ?? null,
1942
+ refundedAmount: refund.refunded_amount ?? null,
1943
+ currency: refund.currency ?? null,
1944
+ status: refund.status ?? null,
1945
+ breakdown: refund.breakdown ? {
1946
+ fromCreator: refund.breakdown.from_creator,
1947
+ fromPlatform: refund.breakdown.from_platform
1948
+ } : null,
1949
+ isFullRefund: refund.is_full_refund ?? null,
1950
+ repairPending: refund.repair_pending ?? null
1951
+ }
1952
+ };
1953
+ }
1954
+ async listRefunds(req = {}) {
1955
+ const response = await this.requestGet("refunds", {
1956
+ sale_reference: req.saleReference,
1957
+ limit: req.limit
1958
+ });
1959
+ return {
1960
+ success: response.success,
1961
+ count: response.count ?? (response.refunds || []).length,
1962
+ refunds: (response.refunds || []).map((refund) => ({
1963
+ id: refund.id,
1964
+ transactionId: refund.transaction_id ?? null,
1965
+ referenceId: refund.reference_id ?? null,
1966
+ saleReference: refund.sale_reference ?? null,
1967
+ refundedAmount: refund.refunded_amount,
1968
+ currency: refund.currency,
1969
+ status: refund.status,
1970
+ reason: refund.reason ?? null,
1971
+ refundFrom: refund.refund_from ?? null,
1972
+ externalRefundId: refund.external_refund_id ?? null,
1973
+ createdAt: refund.created_at ?? null,
1974
+ breakdown: refund.breakdown ? {
1975
+ fromCreator: refund.breakdown.from_creator,
1976
+ fromPlatform: refund.breakdown.from_platform
1977
+ } : null,
1978
+ repairPending: refund.repair_pending ?? null,
1979
+ lastError: refund.last_error ?? null
1980
+ }))
1981
+ };
1982
+ }
1983
+ // === INVOICES ===
1984
+ async createInvoice(req) {
1985
+ return this.request("invoices", {
1986
+ customer_name: req.customerName,
1987
+ customer_email: req.customerEmail,
1988
+ customer_id: req.customerId,
1989
+ customer_address: req.customerAddress ? {
1990
+ line1: req.customerAddress.line1,
1991
+ line2: req.customerAddress.line2,
1992
+ city: req.customerAddress.city,
1993
+ state: req.customerAddress.state,
1994
+ postal_code: req.customerAddress.postalCode,
1995
+ country: req.customerAddress.country
1996
+ } : void 0,
1997
+ line_items: req.lineItems.map((item) => ({
1998
+ description: item.description,
1999
+ quantity: item.quantity,
2000
+ unit_price: item.unitPrice,
2001
+ amount: item.amount ?? Math.round(item.quantity * item.unitPrice)
2002
+ })),
2003
+ due_date: req.dueDate,
2004
+ notes: req.notes,
2005
+ terms: req.terms,
2006
+ reference_id: req.referenceId,
2007
+ metadata: req.metadata
2008
+ });
2009
+ }
2010
+ async listInvoices(options) {
2011
+ return this.requestGet("invoices", {
2012
+ status: options?.status,
2013
+ customer_id: options?.customerId,
2014
+ limit: options?.limit,
2015
+ offset: options?.offset
2016
+ });
2017
+ }
2018
+ async getInvoice(invoiceId) {
2019
+ return this.requestGet(`invoices/${invoiceId}`);
2020
+ }
2021
+ async sendInvoice(invoiceId) {
2022
+ return this.request(`invoices/${invoiceId}/send`, {});
2023
+ }
2024
+ async recordInvoicePayment(invoiceId, req) {
2025
+ return this.request(`invoices/${invoiceId}/record-payment`, {
2026
+ amount: req.amount,
2027
+ payment_method: req.paymentMethod,
2028
+ payment_date: req.paymentDate,
2029
+ reference_id: req.referenceId,
2030
+ notes: req.notes
2031
+ });
2032
+ }
2033
+ async voidInvoice(invoiceId, reason) {
2034
+ return this.request(`invoices/${invoiceId}/void`, { reason });
2035
+ }
2036
+ // === PAY BILL ===
2037
+ async payBill(req) {
2038
+ return this.request("pay-bill", {
2039
+ bill_transaction_id: req.billTransactionId,
2040
+ amount: req.amount,
2041
+ vendor_name: req.vendorName,
2042
+ reference_id: req.referenceId,
2043
+ payment_method: req.paymentMethod,
2044
+ payment_date: req.paymentDate,
2045
+ metadata: req.metadata
2046
+ });
2047
+ }
2048
+ // === BUDGETS ===
2049
+ async createBudget(req) {
2050
+ return this.request("manage-budgets", {
2051
+ name: req.name,
2052
+ category_code: req.categoryCode,
2053
+ budget_amount: req.budgetAmount,
2054
+ budget_period: req.budgetPeriod,
2055
+ alert_at_percentage: req.alertAtPercentage
2056
+ });
2057
+ }
2058
+ async listBudgets() {
2059
+ return this.requestGet("manage-budgets");
2060
+ }
2061
+ // === RECURRING EXPENSES ===
2062
+ async createRecurring(req) {
2063
+ return this.request("manage-recurring", {
2064
+ name: req.name,
2065
+ merchant_name: req.merchantName,
2066
+ category_code: req.categoryCode,
2067
+ amount: req.amount,
2068
+ recurrence_interval: req.recurrenceInterval,
2069
+ recurrence_day: req.recurrenceDay,
2070
+ start_date: req.startDate,
2071
+ end_date: req.endDate,
2072
+ business_purpose: req.businessPurpose,
2073
+ is_variable_amount: req.isVariableAmount
2074
+ });
2075
+ }
2076
+ async listRecurring() {
2077
+ return this.requestGet("manage-recurring");
2078
+ }
2079
+ async getDueRecurring(days) {
2080
+ return this.requestGet("manage-recurring/due", { days });
2081
+ }
2082
+ // === CONTRACTORS ===
2083
+ async createContractor(req) {
2084
+ return this.request("manage-contractors", {
2085
+ name: req.name,
2086
+ email: req.email,
2087
+ company_name: req.companyName
2088
+ });
2089
+ }
2090
+ async listContractors() {
2091
+ return this.requestGet("manage-contractors");
2092
+ }
2093
+ async recordContractorPayment(req) {
2094
+ return this.request("manage-contractors/payment", {
2095
+ contractor_id: req.contractorId,
2096
+ amount: req.amount,
2097
+ payment_date: req.paymentDate,
2098
+ payment_method: req.paymentMethod,
2099
+ payment_reference: req.paymentReference,
2100
+ description: req.description
2101
+ });
2102
+ }
2103
+ // === BANK ACCOUNTS ===
2104
+ async createBankAccount(req) {
2105
+ return this.request("manage-bank-accounts", {
2106
+ bank_name: req.bankName,
2107
+ account_name: req.accountName,
2108
+ account_type: req.accountType,
2109
+ account_last_four: req.accountLastFour
2110
+ });
2111
+ }
2112
+ async listBankAccounts() {
2113
+ return this.requestGet("manage-bank-accounts");
2114
+ }
2115
+ // === LEDGER LISTING ===
2116
+ async listLedgers() {
2117
+ return this.requestGet("list-ledgers");
2118
+ }
2119
+ // === DELETE CREATOR ===
2120
+ async deleteCreator(creatorId) {
2121
+ return this.request("delete-creator", {
2122
+ creator_id: creatorId
2123
+ });
2124
+ }
2125
+ // === TAX INFO ===
2126
+ async submitTaxInfo(req) {
2127
+ return this.request("submit-tax-info", {
2128
+ participant_id: req.participantId,
2129
+ legal_name: req.legalName,
2130
+ tax_id_type: req.taxIdType,
2131
+ tax_id_last4: req.taxIdLast4,
2132
+ business_type: req.businessType,
2133
+ address: req.address ? {
2134
+ line1: req.address.line1,
2135
+ line2: req.address.line2,
2136
+ city: req.address.city,
2137
+ state: req.address.state,
2138
+ postal_code: req.address.postalCode,
2139
+ country: req.address.country
2140
+ } : void 0,
2141
+ certify: req.certify
2142
+ });
2143
+ }
2144
+ // === BANK STATEMENT IMPORT ===
2145
+ async importBankStatement(req) {
2146
+ return this.request("import-bank-statement", {
2147
+ bank_account_id: req.bankAccountId,
2148
+ lines: req.lines.map((line) => ({
2149
+ transaction_date: line.transactionDate,
2150
+ post_date: line.postDate,
2151
+ description: line.description,
2152
+ amount: line.amount,
2153
+ reference_number: line.referenceNumber,
2154
+ check_number: line.checkNumber,
2155
+ merchant_name: line.merchantName,
2156
+ category_hint: line.categoryHint
2157
+ })),
2158
+ auto_match: req.autoMatch
2159
+ });
2160
+ }
2161
+ };
2162
+ var client_default = Soledgic;
2163
+ export {
2164
+ AuthenticationError,
2165
+ ConflictError,
2166
+ DEFAULT_API_VERSION,
2167
+ DEFAULT_BASE_URL,
2168
+ NotFoundError,
2169
+ Soledgic,
2170
+ SoledgicError,
2171
+ ValidationError,
2172
+ client_default as default,
2173
+ hmacHex,
2174
+ isArrayBufferView,
2175
+ mapWebhookDelivery,
2176
+ mapWebhookEndpoint,
2177
+ parseWebhookEvent,
2178
+ parseWebhookSignatureHeader,
2179
+ resolveWebhookEndpointUrl,
2180
+ timingSafeEqual,
2181
+ verifyWebhookSignature,
2182
+ webhookPayloadToString
2183
+ };