@taxora/sdk 1.8.0 → 1.9.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.cjs CHANGED
@@ -24,12 +24,14 @@ __export(index_exports, {
24
24
  AuthEndpoint: () => AuthEndpoint,
25
25
  AuthRetryHttpClient: () => AuthRetryHttpClient,
26
26
  AuthenticationException: () => AuthenticationException,
27
+ BillingEndpoint: () => BillingEndpoint,
27
28
  CompanyAddress: () => CompanyAddress,
28
29
  CompanyEndpoint: () => CompanyEndpoint,
29
30
  ComplianceDocumentType: () => ComplianceDocumentType,
30
31
  ComplianceEnrollment: () => ComplianceEnrollment,
31
32
  ComplianceEnrollmentPage: () => ComplianceEnrollmentPage,
32
33
  ComplianceEnrollmentStatus: () => ComplianceEnrollmentStatus,
34
+ ComplianceOfferings: () => ComplianceOfferings,
33
35
  ComplianceService: () => ComplianceService,
34
36
  ComplianceTaxReport: () => ComplianceTaxReport,
35
37
  ComplianceTaxReportPage: () => ComplianceTaxReportPage,
@@ -73,6 +75,8 @@ __export(index_exports, {
73
75
  TaxoraClientFactory: () => TaxoraClientFactory,
74
76
  TaxoraException: () => TaxoraException,
75
77
  Token: () => Token,
78
+ UsageSummary: () => UsageSummary,
79
+ UsageSummaryPage: () => UsageSummaryPage,
76
80
  ValidationException: () => ValidationException,
77
81
  VatCertificateExport: () => VatCertificateExport,
78
82
  VatCollection: () => VatCollection,
@@ -101,6 +105,7 @@ __export(index_exports, {
101
105
  generateWebhookSignatureHeader: () => generateWebhookSignatureHeader,
102
106
  getBaseUrl: () => getBaseUrl,
103
107
  getFailedVatStates: () => getFailedVatStates,
108
+ isTransactionBuyerRejected: () => isTransactionBuyerRejected,
104
109
  parseLocalTaxNumbersCsv: () => parseLocalTaxNumbersCsv,
105
110
  parseWebhookSignatureHeader: () => parseWebhookSignatureHeader,
106
111
  toComplianceDocumentType: () => toComplianceDocumentType,
@@ -559,6 +564,213 @@ var AuthEndpoint = class {
559
564
  }
560
565
  };
561
566
 
567
+ // src/dto/UsageSummary.ts
568
+ function asRecord(value) {
569
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
570
+ }
571
+ function asRecordList(value) {
572
+ return Array.isArray(value) ? value.filter((row) => asRecord(row) !== null) : [];
573
+ }
574
+ function asString(value, fallback = "") {
575
+ return typeof value === "string" ? value : fallback;
576
+ }
577
+ function asNullableString(value) {
578
+ return typeof value === "string" ? value : null;
579
+ }
580
+ function asNumber(value) {
581
+ return typeof value === "number" ? value : Number(value ?? 0) || 0;
582
+ }
583
+ function asNullableNumber(value) {
584
+ if (value === null || value === void 0 || value === "") return null;
585
+ const num = Number(value);
586
+ return Number.isFinite(num) ? num : null;
587
+ }
588
+ var UsageSummary = class _UsageSummary {
589
+ constructor(id, companyId, feature, country, regime, billingPeriod, eventCount, billableAmount, state, stateLabel, periodClosedAt, billingTriggeredAt, billedAt, stripeInvoiceId, stripeSubscriptionItemId, billingNotes, events, createdAt, updatedAt) {
590
+ this.id = id;
591
+ this.companyId = companyId;
592
+ this.feature = feature;
593
+ this.country = country;
594
+ this.regime = regime;
595
+ this.billingPeriod = billingPeriod;
596
+ this.eventCount = eventCount;
597
+ this.billableAmount = billableAmount;
598
+ this.state = state;
599
+ this.stateLabel = stateLabel;
600
+ this.periodClosedAt = periodClosedAt;
601
+ this.billingTriggeredAt = billingTriggeredAt;
602
+ this.billedAt = billedAt;
603
+ this.stripeInvoiceId = stripeInvoiceId;
604
+ this.stripeSubscriptionItemId = stripeSubscriptionItemId;
605
+ this.billingNotes = billingNotes;
606
+ this.events = events;
607
+ this.createdAt = createdAt;
608
+ this.updatedAt = updatedAt;
609
+ }
610
+ id;
611
+ companyId;
612
+ feature;
613
+ country;
614
+ regime;
615
+ billingPeriod;
616
+ eventCount;
617
+ billableAmount;
618
+ state;
619
+ stateLabel;
620
+ periodClosedAt;
621
+ billingTriggeredAt;
622
+ billedAt;
623
+ stripeInvoiceId;
624
+ stripeSubscriptionItemId;
625
+ billingNotes;
626
+ events;
627
+ createdAt;
628
+ updatedAt;
629
+ static fromArray(data) {
630
+ const amount = data["billable_amount"];
631
+ return new _UsageSummary(
632
+ asNumber(data["id"]),
633
+ asNumber(data["company_id"]),
634
+ asString(data["feature"]),
635
+ asNullableString(data["country"]),
636
+ asNullableString(data["regime"]),
637
+ asString(data["billing_period"]),
638
+ asNumber(data["event_count"]),
639
+ typeof amount === "string" ? amount : typeof amount === "number" ? String(amount) : null,
640
+ asNullableString(data["state"]),
641
+ asNullableString(data["state_label"]),
642
+ asNullableString(data["period_closed_at"]),
643
+ asNullableString(data["billing_triggered_at"]),
644
+ asNullableString(data["billed_at"]),
645
+ asNullableString(data["stripe_invoice_id"]),
646
+ asNullableString(data["stripe_subscription_item_id"]),
647
+ asNullableString(data["billing_notes"]),
648
+ asRecordList(data["events"]).map((event) => ({
649
+ id: asNumber(event["id"]),
650
+ usageSummaryId: asNullableNumber(event["usage_summary_id"]),
651
+ feature: asString(event["feature"]),
652
+ country: asNullableString(event["country"]),
653
+ regime: asNullableString(event["regime"]),
654
+ billingPeriod: asString(event["billing_period"]),
655
+ resourceType: asNullableString(event["resource_type"]),
656
+ resourceId: asNullableNumber(event["resource_id"]),
657
+ stripeUsageRecordId: asNullableString(event["stripe_usage_record_id"]),
658
+ stripeReportedAt: asNullableString(event["stripe_reported_at"]),
659
+ createdAt: asNullableString(event["created_at"])
660
+ })),
661
+ asNullableString(data["created_at"]),
662
+ asNullableString(data["updated_at"])
663
+ );
664
+ }
665
+ };
666
+ var UsageSummaryPage = class _UsageSummaryPage {
667
+ constructor(rows, currentPage, perPage, total, lastPage) {
668
+ this.rows = rows;
669
+ this.currentPage = currentPage;
670
+ this.perPage = perPage;
671
+ this.total = total;
672
+ this.lastPage = lastPage;
673
+ }
674
+ rows;
675
+ currentPage;
676
+ perPage;
677
+ total;
678
+ lastPage;
679
+ static fromResponse(payload) {
680
+ const obj = asRecord(payload) ?? {};
681
+ const rows = asRecordList(obj["data"]).map(UsageSummary.fromArray);
682
+ const meta = asRecord(obj["meta"]) ?? {};
683
+ const num = (value, fallback) => typeof value === "number" ? value : fallback;
684
+ return new _UsageSummaryPage(
685
+ rows,
686
+ num(meta["current_page"], 1),
687
+ num(meta["per_page"], rows.length),
688
+ num(meta["total"], rows.length),
689
+ num(meta["last_page"], 1)
690
+ );
691
+ }
692
+ [Symbol.iterator]() {
693
+ return this.rows[Symbol.iterator]();
694
+ }
695
+ get length() {
696
+ return this.rows.length;
697
+ }
698
+ };
699
+
700
+ // src/endpoints/BillingEndpoint.ts
701
+ var PERIOD_REGEX = /^\d{4}-(0[1-9]|1[0-2])$/;
702
+ var BillingEndpoint = class {
703
+ constructor(baseUrl, apiKey, tokenStorage, httpClient, retryPolicy = new RetryPolicy()) {
704
+ this.baseUrl = baseUrl;
705
+ this.apiKey = apiKey;
706
+ this.tokenStorage = tokenStorage;
707
+ this.httpClient = httpClient;
708
+ this.retryPolicy = retryPolicy;
709
+ }
710
+ baseUrl;
711
+ apiKey;
712
+ tokenStorage;
713
+ httpClient;
714
+ retryPolicy;
715
+ /** Paginated usage summaries, newest billing period first. `perPage` is clamped to 1-100 server-side. */
716
+ async listUsageSummaries(page = 1, perPage = 25) {
717
+ const params = new URLSearchParams();
718
+ params.set("page", String(page));
719
+ params.set("per_page", String(perPage));
720
+ const data = await this.getJson(`${this.baseUrl}/billing/usage-summaries?${params.toString()}`);
721
+ return UsageSummaryPage.fromResponse(data);
722
+ }
723
+ /**
724
+ * The usage summaries of one billing period (YYYY-MM), one per feature,
725
+ * each with its usage events. A period without usage yields a 404 (HttpException).
726
+ */
727
+ async getUsageSummaries(period) {
728
+ if (!PERIOD_REGEX.test(period)) {
729
+ throw new TaxoraException(`Invalid billing period "${period}". Expected YYYY-MM, e.g. "2026-09".`);
730
+ }
731
+ const data = await this.getJson(`${this.baseUrl}/billing/usage-summaries/${period}`);
732
+ return Array.isArray(data) ? data.filter((row) => typeof row === "object" && row !== null).map(UsageSummary.fromArray) : [];
733
+ }
734
+ buildHeaders() {
735
+ const headers = {
736
+ "Content-Type": "application/json",
737
+ "x-api-key": this.apiKey
738
+ };
739
+ const token = this.tokenStorage.get();
740
+ if (token) {
741
+ headers["Authorization"] = `Bearer ${token.accessToken}`;
742
+ }
743
+ return headers;
744
+ }
745
+ /** GET + envelope unwrap (`{success, data}` → data, which may be an object or an array). */
746
+ async getJson(url) {
747
+ return withRetries(this.retryPolicy, "billing request", async () => {
748
+ const response = await this.httpClient.request("GET", url, { headers: this.buildHeaders() });
749
+ const responseText = await response.text();
750
+ if (!response.ok) {
751
+ throw new HttpException(
752
+ describeApiError(responseText, response.status),
753
+ response.status,
754
+ responseText,
755
+ {},
756
+ response.headers.get("retry-after")
757
+ );
758
+ }
759
+ let parsed;
760
+ try {
761
+ parsed = JSON.parse(responseText);
762
+ } catch {
763
+ throw new HttpException("Invalid JSON response", response.status, responseText);
764
+ }
765
+ if (typeof parsed !== "object" || parsed === null) {
766
+ throw new HttpException("Unexpected response format", response.status, responseText);
767
+ }
768
+ const obj = parsed;
769
+ return obj["data"] !== void 0 && obj["data"] !== null ? obj["data"] : obj;
770
+ });
771
+ }
772
+ };
773
+
562
774
  // src/dto/CompanyResource.ts
563
775
  function normalizeCompanyResource(data) {
564
776
  const apiRateLimit = typeof data["api_rate_limit"] === "number" ? data["api_rate_limit"] : void 0;
@@ -685,13 +897,13 @@ function describeComplianceService(service) {
685
897
  }
686
898
 
687
899
  // src/dto/ComplianceEnrollment.ts
688
- function asString(value, fallback = "") {
900
+ function asString2(value, fallback = "") {
689
901
  return typeof value === "string" ? value : fallback;
690
902
  }
691
- function asNullableString(value) {
903
+ function asNullableString2(value) {
692
904
  return typeof value === "string" ? value : null;
693
905
  }
694
- function asNumber(value) {
906
+ function asNumber2(value) {
695
907
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
696
908
  }
697
909
  var ComplianceEnrollment = class _ComplianceEnrollment {
@@ -738,29 +950,114 @@ var ComplianceEnrollment = class _ComplianceEnrollment {
738
950
  static fromArray(data) {
739
951
  const regimeConfig = typeof data["regime_config"] === "object" && data["regime_config"] !== null && !Array.isArray(data["regime_config"]) ? data["regime_config"] : null;
740
952
  return new _ComplianceEnrollment(
741
- asNumber(data["id"]),
742
- asNumber(data["company_id"]),
743
- asString(data["country"]),
744
- asString(data["regime"]),
745
- asString(data["provider"]),
953
+ asNumber2(data["id"]),
954
+ asNumber2(data["company_id"]),
955
+ asString2(data["country"]),
956
+ asString2(data["regime"]),
957
+ asString2(data["provider"]),
746
958
  toComplianceEnrollmentStatus(data["status"]),
747
- asString(data["status_label"]),
748
- asNullableString(data["status_error"]),
749
- asNullableString(data["provider_account_id"]),
750
- asNullableString(data["tax_id"]),
751
- asNullableString(data["company_register_id"]),
752
- asNullableString(data["company_register_scheme"]),
959
+ asString2(data["status_label"]),
960
+ asNullableString2(data["status_error"]),
961
+ asNullableString2(data["provider_account_id"]),
962
+ asNullableString2(data["tax_id"]),
963
+ asNullableString2(data["company_register_id"]),
964
+ asNullableString2(data["company_register_scheme"]),
753
965
  regimeConfig,
754
- asNullableString(data["reporting_start_date"]),
755
- asNullableString(data["notification_email"]),
966
+ asNullableString2(data["reporting_start_date"]),
967
+ asNullableString2(data["notification_email"]),
756
968
  data["auto_send"] === true,
757
- asNullableString(data["created_at"]),
758
- asNullableString(data["updated_at"]),
969
+ asNullableString2(data["created_at"]),
970
+ asNullableString2(data["updated_at"]),
759
971
  toComplianceService(data["service"])
760
972
  );
761
973
  }
762
974
  };
763
975
 
976
+ // src/dto/ComplianceOfferings.ts
977
+ function asRecord2(value) {
978
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
979
+ }
980
+ function asRecordList2(value) {
981
+ return Array.isArray(value) ? value.filter((row) => asRecord2(row) !== null) : [];
982
+ }
983
+ function asString3(value, fallback = "") {
984
+ return typeof value === "string" ? value : fallback;
985
+ }
986
+ function asNullableString3(value) {
987
+ return typeof value === "string" ? value : null;
988
+ }
989
+ function asNullableNumber2(value) {
990
+ if (typeof value === "number" && Number.isFinite(value)) return value;
991
+ if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
992
+ return null;
993
+ }
994
+ function asStringList(value) {
995
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
996
+ }
997
+ function toRequires(value) {
998
+ const record = asRecord2(value);
999
+ return record === null ? null : { country: asString3(record["country"]), service: asString3(record["service"]) };
1000
+ }
1001
+ var ComplianceOfferings = class _ComplianceOfferings {
1002
+ constructor(offerings, coverage, access, accessByCountry) {
1003
+ this.offerings = offerings;
1004
+ this.coverage = coverage;
1005
+ this.access = access;
1006
+ this.accessByCountry = accessByCountry;
1007
+ }
1008
+ offerings;
1009
+ coverage;
1010
+ access;
1011
+ accessByCountry;
1012
+ static fromArray(data) {
1013
+ const offerings = asRecordList2(data["data"]).map((row) => ({
1014
+ country: asString3(row["country"]),
1015
+ service: asString3(row["service"]),
1016
+ currency: asString3(row["currency"], "EUR"),
1017
+ active: row["active"] === true,
1018
+ viaStripe: row["via_stripe"] === true,
1019
+ plan: asNullableString3(row["plan"]),
1020
+ status: asNullableString3(row["status"]),
1021
+ enrolled: row["enrolled"] === true,
1022
+ plans: asRecordList2(row["plans"]).map((plan) => ({
1023
+ key: asString3(plan["key"]),
1024
+ monthlyFee: asNullableNumber2(plan["monthly_fee"]),
1025
+ setupFee: asNullableNumber2(plan["setup_fee"]),
1026
+ usageTiers: Array.isArray(plan["usage_tiers"]) ? plan["usage_tiers"] : [],
1027
+ volumeLimit: plan["volume_limit"] ?? null,
1028
+ contactOnly: plan["contact_only"] === true,
1029
+ checkoutAvailable: plan["checkout_available"] === true,
1030
+ requires: toRequires(plan["requires"]),
1031
+ eligible: plan["eligible"] === true
1032
+ }))
1033
+ }));
1034
+ const coverage = asRecordList2(data["coverage"]).map((row) => ({
1035
+ country: asString3(row["country"]),
1036
+ availability: asString3(row["availability"]),
1037
+ services: asStringList(row["services"]),
1038
+ network: asNullableString3(row["network"]),
1039
+ format: asNullableString3(row["format"]),
1040
+ mandate: asNullableString3(row["mandate"]),
1041
+ support: asString3(row["support"], "yes")
1042
+ }));
1043
+ const access = asRecord2(data["access"]) ?? {};
1044
+ const accessByCountry = {};
1045
+ for (const [country, services] of Object.entries(asRecord2(data["access_by_country"]) ?? {})) {
1046
+ const flags = {};
1047
+ for (const [service, value] of Object.entries(asRecord2(services) ?? {})) {
1048
+ flags[service] = value === true;
1049
+ }
1050
+ accessByCountry[country] = flags;
1051
+ }
1052
+ return new _ComplianceOfferings(
1053
+ offerings,
1054
+ coverage,
1055
+ { eReporting: access["e_reporting"] === true, eInvoicing: access["e_invoicing"] === true },
1056
+ accessByCountry
1057
+ );
1058
+ }
1059
+ };
1060
+
764
1061
  // src/dto/ComplianceEnrollmentPage.ts
765
1062
  var ComplianceEnrollmentPage = class _ComplianceEnrollmentPage {
766
1063
  constructor(rows, currentPage, perPage, total, lastPage) {
@@ -830,16 +1127,16 @@ function describeComplianceTaxReportState(state) {
830
1127
  }
831
1128
 
832
1129
  // src/dto/ComplianceTaxReport.ts
833
- function asString2(value, fallback = "") {
1130
+ function asString4(value, fallback = "") {
834
1131
  return typeof value === "string" ? value : fallback;
835
1132
  }
836
- function asNullableString2(value) {
1133
+ function asNullableString4(value) {
837
1134
  return typeof value === "string" ? value : null;
838
1135
  }
839
- function asNumber2(value) {
1136
+ function asNumber3(value) {
840
1137
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
841
1138
  }
842
- function asNullableNumber(value) {
1139
+ function asNullableNumber3(value) {
843
1140
  return typeof value === "number" ? value : null;
844
1141
  }
845
1142
  function asMoney(value) {
@@ -890,25 +1187,25 @@ var ComplianceTaxReport = class _ComplianceTaxReport {
890
1187
  updatedAt;
891
1188
  static fromArray(data) {
892
1189
  return new _ComplianceTaxReport(
893
- asNumber2(data["id"]),
894
- asNumber2(data["company_id"]),
895
- asNullableNumber(data["compliance_transaction_id"]),
896
- asNullableNumber(data["ledger_id"]),
897
- asString2(data["country"]),
898
- asString2(data["regime"]),
1190
+ asNumber3(data["id"]),
1191
+ asNumber3(data["company_id"]),
1192
+ asNullableNumber3(data["compliance_transaction_id"]),
1193
+ asNullableNumber3(data["ledger_id"]),
1194
+ asString4(data["country"]),
1195
+ asString4(data["regime"]),
899
1196
  toComplianceTaxReportState(data["state"]),
900
- asString2(data["state_label"]),
1197
+ asString4(data["state_label"]),
901
1198
  data["is_terminal"] === true,
902
- asNullableString2(data["provider_tax_report_id"]),
903
- asNullableString2(data["provider_ledger_id"]),
1199
+ asNullableString4(data["provider_tax_report_id"]),
1200
+ asNullableString4(data["provider_ledger_id"]),
904
1201
  asMoney(data["base_amount"]),
905
1202
  asMoney(data["tax_amount"]),
906
1203
  asMoney(data["total_amount"]),
907
- asNullableString2(data["refusal_reason"]),
908
- asNullableString2(data["registered_at"]),
909
- asNullableString2(data["refused_at"]),
910
- asNullableString2(data["created_at"]),
911
- asNullableString2(data["updated_at"])
1204
+ asNullableString4(data["refusal_reason"]),
1205
+ asNullableString4(data["registered_at"]),
1206
+ asNullableString4(data["refused_at"]),
1207
+ asNullableString4(data["created_at"]),
1208
+ asNullableString4(data["updated_at"])
912
1209
  );
913
1210
  }
914
1211
  };
@@ -979,6 +1276,8 @@ var ComplianceTransactionState = {
979
1276
  SENDING: "sending",
980
1277
  SUBMITTED: "submitted",
981
1278
  ERROR: "error",
1279
+ /** E-invoicing only: the buyer cannot receive e-invoices — nothing was sent or billed; send your regular invoice. */
1280
+ NOT_REQUIRED: "not_required",
982
1281
  UNKNOWN: "unknown"
983
1282
  };
984
1283
  var VALUES5 = Object.values(ComplianceTransactionState);
@@ -996,6 +1295,7 @@ var DESCRIPTIONS5 = {
996
1295
  [ComplianceTransactionState.SENDING]: "Submission to the provider in progress.",
997
1296
  [ComplianceTransactionState.SUBMITTED]: "Successfully submitted to the provider.",
998
1297
  [ComplianceTransactionState.ERROR]: "Submission failed. See submissionError.",
1298
+ [ComplianceTransactionState.NOT_REQUIRED]: "The buyer cannot receive e-invoices, so none was sent or billed. Send your regular invoice instead.",
999
1299
  [ComplianceTransactionState.UNKNOWN]: "Unknown state."
1000
1300
  };
1001
1301
  function describeComplianceTransactionState(state) {
@@ -1034,13 +1334,13 @@ function describeComplianceTransactionType(type) {
1034
1334
  }
1035
1335
 
1036
1336
  // src/dto/ComplianceTransaction.ts
1037
- function asString3(value, fallback = "") {
1337
+ function asString5(value, fallback = "") {
1038
1338
  return typeof value === "string" ? value : fallback;
1039
1339
  }
1040
- function asNullableString3(value) {
1340
+ function asNullableString5(value) {
1041
1341
  return typeof value === "string" ? value : null;
1042
1342
  }
1043
- function asNumber3(value) {
1343
+ function asNumber4(value) {
1044
1344
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
1045
1345
  }
1046
1346
  function asMoney2(value) {
@@ -1048,34 +1348,55 @@ function asMoney2(value) {
1048
1348
  if (typeof value === "number" && Number.isFinite(value)) return String(value);
1049
1349
  return "0.00";
1050
1350
  }
1051
- function asNullableNumber2(value) {
1351
+ function asNullableNumber4(value) {
1052
1352
  if (typeof value === "number" && Number.isFinite(value)) return value;
1053
1353
  if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
1054
1354
  return null;
1055
1355
  }
1056
- function asRecord(value) {
1356
+ function asRecord3(value) {
1057
1357
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
1058
1358
  }
1059
- function asRecordList(value) {
1060
- return Array.isArray(value) ? value.filter((row) => asRecord(row) !== null) : [];
1359
+ function asRecordList3(value) {
1360
+ return Array.isArray(value) ? value.filter((row) => asRecord3(row) !== null) : [];
1361
+ }
1362
+ function toInvoicePdf(value) {
1363
+ const pdf = asRecord3(value);
1364
+ if (pdf === null) return null;
1365
+ return {
1366
+ filename: asNullableString5(pdf["filename"]),
1367
+ size: asNullableNumber4(pdf["size"]),
1368
+ attached: pdf["attached"] === true
1369
+ };
1370
+ }
1371
+ function toEurEquivalent(value) {
1372
+ const eur = asRecord3(value);
1373
+ if (eur === null) return null;
1374
+ return {
1375
+ subtotal: asMoney2(eur["subtotal"]),
1376
+ taxAmount: asMoney2(eur["tax_amount"]),
1377
+ total: asMoney2(eur["total"]),
1378
+ rate: asString5(eur["rate"]),
1379
+ rateDate: asNullableString5(eur["rate_date"]),
1380
+ source: asString5(eur["source"], "ECB")
1381
+ };
1061
1382
  }
1062
1383
  function toInvoiceLines(providerPayload) {
1063
- const invoice = asRecord(asRecord(providerPayload)?.["invoice"]);
1064
- return asRecordList(invoice?.["invoice_lines_attributes"]).map((line) => ({
1065
- description: asString3(line["description"]),
1066
- quantity: asNullableNumber2(line["quantity"]),
1384
+ const invoice = asRecord3(asRecord3(providerPayload)?.["invoice"]);
1385
+ return asRecordList3(invoice?.["invoice_lines_attributes"]).map((line) => ({
1386
+ description: asString5(line["description"]),
1387
+ quantity: asNullableNumber4(line["quantity"]),
1067
1388
  price: asMoney2(line["price"]),
1068
- unit: asNullableNumber2(line["unit"]),
1069
- taxes: asRecordList(line["taxes_attributes"]).map((tax) => ({
1070
- name: asString3(tax["name"]),
1071
- percent: asNullableNumber2(tax["percent"]),
1072
- category: asNullableString3(tax["category"]),
1073
- comment: asNullableString3(tax["comment"])
1389
+ unit: asNullableNumber4(line["unit"]),
1390
+ taxes: asRecordList3(line["taxes_attributes"]).map((tax) => ({
1391
+ name: asString5(tax["name"]),
1392
+ percent: asNullableNumber4(tax["percent"]),
1393
+ category: asNullableString5(tax["category"]),
1394
+ comment: asNullableString5(tax["comment"])
1074
1395
  }))
1075
1396
  }));
1076
1397
  }
1077
1398
  var ComplianceTransaction = class _ComplianceTransaction {
1078
- constructor(id, companyId, complianceEnrollmentId, country, regime, transactionType, transactionTypeLabel, state, stateLabel, invoiceNumber, invoiceDate, dueDate, currency, subtotal, taxAmount, total, counterpartyName, counterpartyCountry, counterpartyVatNumber, isPaid, paidAt, providerInvoiceId, submissionError, reportedAt, taxReport, createdAt, updatedAt, counterpartyRegisterId = null, counterpartyAddress = null, counterpartyCity = null, counterpartyPostalcode = null, counterpartyEmail = null, buyerReference = null, documentType = ComplianceDocumentType.INVOICE, amendedNumber = null, amendedDate = null, providerState = null, invoiceLines = []) {
1399
+ constructor(id, companyId, complianceEnrollmentId, country, regime, transactionType, transactionTypeLabel, state, stateLabel, invoiceNumber, invoiceDate, dueDate, currency, subtotal, taxAmount, total, counterpartyName, counterpartyCountry, counterpartyVatNumber, isPaid, paidAt, providerInvoiceId, submissionError, reportedAt, taxReport, createdAt, updatedAt, counterpartyRegisterId = null, counterpartyAddress = null, counterpartyCity = null, counterpartyPostalcode = null, counterpartyEmail = null, buyerReference = null, documentType = ComplianceDocumentType.INVOICE, amendedNumber = null, amendedDate = null, providerState = null, invoiceLines = [], documentUrl = null, deliveryCheck = null, invoicePdf = null, internalReference = null, pdfUrl = null, buyerRejected = false, rejectionReason = null, eurEquivalent = null) {
1079
1400
  this.id = id;
1080
1401
  this.companyId = companyId;
1081
1402
  this.complianceEnrollmentId = complianceEnrollmentId;
@@ -1114,6 +1435,14 @@ var ComplianceTransaction = class _ComplianceTransaction {
1114
1435
  this.amendedDate = amendedDate;
1115
1436
  this.providerState = providerState;
1116
1437
  this.invoiceLines = invoiceLines;
1438
+ this.documentUrl = documentUrl;
1439
+ this.deliveryCheck = deliveryCheck;
1440
+ this.invoicePdf = invoicePdf;
1441
+ this.internalReference = internalReference;
1442
+ this.pdfUrl = pdfUrl;
1443
+ this.buyerRejected = buyerRejected;
1444
+ this.rejectionReason = rejectionReason;
1445
+ this.eurEquivalent = eurEquivalent;
1117
1446
  }
1118
1447
  id;
1119
1448
  companyId;
@@ -1153,50 +1482,66 @@ var ComplianceTransaction = class _ComplianceTransaction {
1153
1482
  amendedDate;
1154
1483
  providerState;
1155
1484
  invoiceLines;
1485
+ documentUrl;
1486
+ deliveryCheck;
1487
+ invoicePdf;
1488
+ internalReference;
1489
+ pdfUrl;
1490
+ buyerRejected;
1491
+ rejectionReason;
1492
+ eurEquivalent;
1156
1493
  get isCreditNote() {
1157
1494
  return this.documentType === ComplianceDocumentType.CREDIT_NOTE;
1158
1495
  }
1159
1496
  static fromArray(data) {
1160
1497
  const taxReport = typeof data["tax_report"] === "object" && data["tax_report"] !== null && !Array.isArray(data["tax_report"]) ? ComplianceTaxReport.fromArray(data["tax_report"]) : void 0;
1161
1498
  return new _ComplianceTransaction(
1162
- asNumber3(data["id"]),
1163
- asNumber3(data["company_id"]),
1164
- asNumber3(data["compliance_enrollment_id"]),
1165
- asString3(data["country"]),
1166
- asString3(data["regime"]),
1499
+ asNumber4(data["id"]),
1500
+ asNumber4(data["company_id"]),
1501
+ asNumber4(data["compliance_enrollment_id"]),
1502
+ asString5(data["country"]),
1503
+ asString5(data["regime"]),
1167
1504
  toComplianceTransactionType(data["transaction_type"]),
1168
- asString3(data["transaction_type_label"]),
1505
+ asString5(data["transaction_type_label"]),
1169
1506
  toComplianceTransactionState(data["state"]),
1170
- asString3(data["state_label"]),
1171
- asString3(data["invoice_number"]),
1172
- asNullableString3(data["invoice_date"]),
1173
- asNullableString3(data["due_date"]),
1174
- asString3(data["currency"], "EUR"),
1507
+ asString5(data["state_label"]),
1508
+ asString5(data["invoice_number"]),
1509
+ asNullableString5(data["invoice_date"]),
1510
+ asNullableString5(data["due_date"]),
1511
+ asString5(data["currency"], "EUR"),
1175
1512
  asMoney2(data["subtotal"]),
1176
1513
  asMoney2(data["tax_amount"]),
1177
1514
  asMoney2(data["total"]),
1178
- asNullableString3(data["counterparty_name"]),
1179
- asNullableString3(data["counterparty_country"]),
1180
- asNullableString3(data["counterparty_vat_number"]),
1515
+ asNullableString5(data["counterparty_name"]),
1516
+ asNullableString5(data["counterparty_country"]),
1517
+ asNullableString5(data["counterparty_vat_number"]),
1181
1518
  data["is_paid"] === true,
1182
- asNullableString3(data["paid_at"]),
1183
- asNullableString3(data["provider_invoice_id"]),
1184
- asNullableString3(data["submission_error"]),
1185
- asNullableString3(data["reported_at"]),
1519
+ asNullableString5(data["paid_at"]),
1520
+ asNullableString5(data["provider_invoice_id"]),
1521
+ asNullableString5(data["submission_error"]),
1522
+ asNullableString5(data["reported_at"]),
1186
1523
  taxReport,
1187
- asNullableString3(data["created_at"]),
1188
- asNullableString3(data["updated_at"]),
1189
- asNullableString3(data["counterparty_register_id"]),
1190
- asNullableString3(data["counterparty_address"]),
1191
- asNullableString3(data["counterparty_city"]),
1192
- asNullableString3(data["counterparty_postalcode"]),
1193
- asNullableString3(data["counterparty_email"]),
1194
- asNullableString3(data["buyer_reference"]),
1524
+ asNullableString5(data["created_at"]),
1525
+ asNullableString5(data["updated_at"]),
1526
+ asNullableString5(data["counterparty_register_id"]),
1527
+ asNullableString5(data["counterparty_address"]),
1528
+ asNullableString5(data["counterparty_city"]),
1529
+ asNullableString5(data["counterparty_postalcode"]),
1530
+ asNullableString5(data["counterparty_email"]),
1531
+ asNullableString5(data["buyer_reference"]),
1195
1532
  data["document_type"] === void 0 || data["document_type"] === null ? ComplianceDocumentType.INVOICE : toComplianceDocumentType(data["document_type"]),
1196
- asNullableString3(data["amended_number"]),
1197
- asNullableString3(data["amended_date"]),
1198
- asNullableString3(data["provider_state"]),
1199
- toInvoiceLines(data["provider_payload"])
1533
+ asNullableString5(data["amended_number"]),
1534
+ asNullableString5(data["amended_date"]),
1535
+ asNullableString5(data["provider_state"]),
1536
+ toInvoiceLines(data["provider_payload"]),
1537
+ asNullableString5(data["document_url"]),
1538
+ asRecord3(data["delivery_check"]),
1539
+ toInvoicePdf(data["invoice_pdf"]),
1540
+ asNullableString5(data["internal_reference"]),
1541
+ asNullableString5(data["pdf_url"]),
1542
+ data["buyer_rejected"] === true,
1543
+ asNullableString5(data["rejection_reason"]),
1544
+ toEurEquivalent(data["eur_equivalent"])
1200
1545
  );
1201
1546
  }
1202
1547
  };
@@ -1283,10 +1628,10 @@ function describePeppolLookupStatus(status) {
1283
1628
  }
1284
1629
 
1285
1630
  // src/dto/PeppolLookupResult.ts
1286
- function asString4(value, fallback = "") {
1631
+ function asString6(value, fallback = "") {
1287
1632
  return typeof value === "string" ? value : fallback;
1288
1633
  }
1289
- function asNullableString4(value) {
1634
+ function asNullableString6(value) {
1290
1635
  return typeof value === "string" ? value : null;
1291
1636
  }
1292
1637
  var PeppolLookupResult = class _PeppolLookupResult {
@@ -1317,21 +1662,21 @@ var PeppolLookupResult = class _PeppolLookupResult {
1317
1662
  return new _PeppolLookupResult(
1318
1663
  toPeppolLookupStatus(data["status"]),
1319
1664
  typeof data["reachable"] === "boolean" ? data["reachable"] : null,
1320
- asString4(data["country"]),
1321
- asString4(data["scheme"]),
1322
- asString4(data["id"]),
1665
+ asString6(data["country"]),
1666
+ asString6(data["scheme"]),
1667
+ asString6(data["id"]),
1323
1668
  documentTypes,
1324
- asNullableString4(data["transport_type_code"]),
1325
- asNullableString4(data["checked_at"])
1669
+ asNullableString6(data["transport_type_code"]),
1670
+ asNullableString6(data["checked_at"])
1326
1671
  );
1327
1672
  }
1328
1673
  };
1329
1674
 
1330
1675
  // src/dto/RegistryCompany.ts
1331
- function asString5(value, fallback = "") {
1676
+ function asString7(value, fallback = "") {
1332
1677
  return typeof value === "string" ? value : fallback;
1333
1678
  }
1334
- function asNullableString5(value) {
1679
+ function asNullableString7(value) {
1335
1680
  return typeof value === "string" ? value : null;
1336
1681
  }
1337
1682
  var RegistryCompany = class _RegistryCompany {
@@ -1363,27 +1708,27 @@ var RegistryCompany = class _RegistryCompany {
1363
1708
  country;
1364
1709
  static fromArray(data) {
1365
1710
  return new _RegistryCompany(
1366
- asString5(data["org_number"]),
1367
- asString5(data["company_name"]),
1368
- asNullableString5(data["organisation_form"]),
1711
+ asString7(data["org_number"]),
1712
+ asString7(data["company_name"]),
1713
+ asNullableString7(data["organisation_form"]),
1369
1714
  data["vat_registered"] === true,
1370
- asNullableString5(data["vat_number"]),
1715
+ asNullableString7(data["vat_number"]),
1371
1716
  data["enterprise_register"] === true,
1372
1717
  data["bankrupt"] === true,
1373
1718
  data["under_liquidation"] === true,
1374
- asNullableString5(data["address"]),
1375
- asNullableString5(data["postalcode"]),
1376
- asNullableString5(data["city"]),
1377
- asString5(data["country"])
1719
+ asNullableString7(data["address"]),
1720
+ asNullableString7(data["postalcode"]),
1721
+ asNullableString7(data["city"]),
1722
+ asString7(data["country"])
1378
1723
  );
1379
1724
  }
1380
1725
  };
1381
1726
 
1382
1727
  // src/dto/RevenueStatistics.ts
1383
- function asString6(value, fallback = "") {
1728
+ function asString8(value, fallback = "") {
1384
1729
  return typeof value === "string" ? value : fallback;
1385
1730
  }
1386
- function asNumber4(value) {
1731
+ function asNumber5(value) {
1387
1732
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
1388
1733
  }
1389
1734
  function asMoney3(value) {
@@ -1395,7 +1740,7 @@ function asRecords(value) {
1395
1740
  }
1396
1741
  function toTotals(data) {
1397
1742
  return {
1398
- count: asNumber4(data["count"]),
1743
+ count: asNumber5(data["count"]),
1399
1744
  subtotal: asMoney3(data["subtotal"]),
1400
1745
  taxAmount: asMoney3(data["tax_amount"]),
1401
1746
  total: asMoney3(data["total"])
@@ -1432,35 +1777,35 @@ var RevenueStatistics = class _RevenueStatistics {
1432
1777
  typeof data["totals"] === "object" && data["totals"] !== null ? data["totals"] : {}
1433
1778
  );
1434
1779
  const timeSeries = asRecords(data["time_series"]).map((row) => ({
1435
- bucket: asString6(row["bucket"]),
1780
+ bucket: asString8(row["bucket"]),
1436
1781
  ...toTotals(row)
1437
1782
  }));
1438
1783
  const byType = asRecords(data["by_type"]).map((row) => ({
1439
- type: asString6(row["type"]),
1440
- typeLabel: asString6(row["type_label"]),
1441
- count: asNumber4(row["count"]),
1784
+ type: asString8(row["type"]),
1785
+ typeLabel: asString8(row["type_label"]),
1786
+ count: asNumber5(row["count"]),
1442
1787
  total: asMoney3(row["total"])
1443
1788
  }));
1444
1789
  const byCountry = asRecords(data["by_country"]).map((row) => ({
1445
- country: asString6(row["country"], "unknown"),
1446
- count: asNumber4(row["count"]),
1790
+ country: asString8(row["country"], "unknown"),
1791
+ count: asNumber5(row["count"]),
1447
1792
  total: asMoney3(row["total"])
1448
1793
  }));
1449
1794
  const byState = asRecords(data["by_state"]).map((row) => ({
1450
- state: asString6(row["state"]),
1451
- stateLabel: asString6(row["state_label"]),
1452
- count: asNumber4(row["count"]),
1795
+ state: asString8(row["state"]),
1796
+ stateLabel: asString8(row["state_label"]),
1797
+ count: asNumber5(row["count"]),
1453
1798
  total: asMoney3(row["total"])
1454
1799
  }));
1455
1800
  const byCurrency = asRecords(data["by_currency"]).map((row) => ({
1456
- currency: asString6(row["currency"]),
1801
+ currency: asString8(row["currency"]),
1457
1802
  ...toTotals(row)
1458
1803
  }));
1459
1804
  return new _RevenueStatistics(
1460
- asString6(range["date_from"]) || void 0,
1461
- asString6(range["date_to"]) || void 0,
1462
- asString6(range["interval"]) || void 0,
1463
- asString6(data["primary_currency"], "EUR"),
1805
+ asString8(range["date_from"]) || void 0,
1806
+ asString8(range["date_to"]) || void 0,
1807
+ asString8(range["interval"]) || void 0,
1808
+ asString8(data["primary_currency"], "EUR"),
1464
1809
  data["is_multi_currency"] === true,
1465
1810
  totals,
1466
1811
  timeSeries,
@@ -1473,10 +1818,10 @@ var RevenueStatistics = class _RevenueStatistics {
1473
1818
  };
1474
1819
 
1475
1820
  // src/dto/SireneLookupResult.ts
1476
- function asString7(value, fallback = "") {
1821
+ function asString9(value, fallback = "") {
1477
1822
  return typeof value === "string" ? value : fallback;
1478
1823
  }
1479
- function asNullableString6(value) {
1824
+ function asNullableString8(value) {
1480
1825
  return typeof value === "string" ? value : null;
1481
1826
  }
1482
1827
  var SireneLookupResult = class _SireneLookupResult {
@@ -1502,24 +1847,24 @@ var SireneLookupResult = class _SireneLookupResult {
1502
1847
  postalcode;
1503
1848
  static fromArray(data) {
1504
1849
  return new _SireneLookupResult(
1505
- asString7(data["company_name"]),
1506
- asString7(data["siren"]),
1507
- asNullableString6(data["siret"]),
1508
- asNullableString6(data["naf_code"]),
1509
- asNullableString6(data["naf_full"]),
1510
- asNullableString6(data["enterprise_size"]),
1511
- asNullableString6(data["address"]),
1512
- asNullableString6(data["city"]),
1513
- asNullableString6(data["postalcode"])
1850
+ asString9(data["company_name"]),
1851
+ asString9(data["siren"]),
1852
+ asNullableString8(data["siret"]),
1853
+ asNullableString8(data["naf_code"]),
1854
+ asNullableString8(data["naf_full"]),
1855
+ asNullableString8(data["enterprise_size"]),
1856
+ asNullableString8(data["address"]),
1857
+ asNullableString8(data["city"]),
1858
+ asNullableString8(data["postalcode"])
1514
1859
  );
1515
1860
  }
1516
1861
  };
1517
1862
 
1518
1863
  // src/dto/VatRates.ts
1519
- function asString8(value, fallback = "") {
1864
+ function asString10(value, fallback = "") {
1520
1865
  return typeof value === "string" ? value : fallback;
1521
1866
  }
1522
- function asNumber5(value) {
1867
+ function asNumber6(value) {
1523
1868
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
1524
1869
  }
1525
1870
  var VatRates = class _VatRates {
@@ -1533,13 +1878,13 @@ var VatRates = class _VatRates {
1533
1878
  rates;
1534
1879
  static fromArray(data) {
1535
1880
  const rates = (Array.isArray(data["rates"]) ? data["rates"] : []).filter((row) => typeof row === "object" && row !== null).map((row) => ({
1536
- percent: asNumber5(row["percent"]),
1537
- category: asString8(row["category"]),
1538
- labelKey: asString8(row["label_key"]),
1539
- taxName: asString8(row["tax_name"]),
1881
+ percent: asNumber6(row["percent"]),
1882
+ category: asString10(row["category"]),
1883
+ labelKey: asString10(row["label_key"]),
1884
+ taxName: asString10(row["tax_name"]),
1540
1885
  requiresVatex: row["requires_vatex"] === true
1541
1886
  }));
1542
- return new _VatRates(asString8(data["country"]), asString8(data["currency"], "EUR"), rates);
1887
+ return new _VatRates(asString10(data["country"]), asString10(data["currency"], "EUR"), rates);
1543
1888
  }
1544
1889
  };
1545
1890
 
@@ -1598,10 +1943,15 @@ var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
1598
1943
  var NAF_CODE_REGEX = /^\d{2}$/;
1599
1944
  var COUNTRY_REGEX = /^[A-Za-z]{2}$/;
1600
1945
  var PEPPOL_SCHEME_REGEX = /^\d{4}$/;
1946
+ var INVOICE_PDF_MAX_BYTES = 10 * 1024 * 1024;
1947
+ var INVOICE_PDF_MAGIC = [37, 80, 68, 70, 45];
1601
1948
  var INTERVALS = ["day", "week", "month"];
1602
1949
  var SERVICES = ["e_reporting", "e_invoicing"];
1603
1950
  var ENTERPRISE_SIZES = ["micro", "pme", "eti", "ge"];
1604
1951
  var TYPE_OPERATIONS = ["services", "goods", "mixed"];
1952
+ var NOTIFICATION_LANGUAGES = ["de", "en"];
1953
+ var NOTIFICATION_DIGESTS = ["off", "daily", "weekly"];
1954
+ var NOTIFICATION_MAX_RECIPIENTS = 5;
1605
1955
  var TRANSACTION_TYPES = [
1606
1956
  "b2c_outbound",
1607
1957
  "b2b_domestic_outbound",
@@ -1796,6 +2146,8 @@ var EReportingEndpoint = class {
1796
2146
  this.validateInvoiceLines(input.invoiceLines);
1797
2147
  this.validateOptionalCodes(input);
1798
2148
  this.validateBuyerFields(input);
2149
+ this.validateInternalReference(input.internalReference);
2150
+ this.validateInvoicePdfFilename(input);
1799
2151
  const body = {
1800
2152
  compliance_enrollment_id: input.complianceEnrollmentId,
1801
2153
  transaction_type: input.transactionType,
@@ -1811,23 +2163,9 @@ var EReportingEndpoint = class {
1811
2163
  const data = await this.parseJsonResponse(response);
1812
2164
  return ComplianceTransaction.fromArray(data);
1813
2165
  }
1814
- /** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country. */
2166
+ /** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country / search / internal reference / provider state. */
1815
2167
  async listTransactions(filters = {}) {
1816
- if (filters.complianceEnrollmentId !== void 0) {
1817
- this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
1818
- }
1819
- if (filters.country !== void 0 && !COUNTRY_REGEX.test(filters.country)) {
1820
- throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
1821
- }
1822
- const params = new URLSearchParams();
1823
- if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
1824
- if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
1825
- if (filters.state !== void 0) params.set("state", filters.state);
1826
- if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
1827
- if (filters.complianceEnrollmentId !== void 0) {
1828
- params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
1829
- }
1830
- if (filters.country !== void 0) params.set("country", filters.country.toUpperCase());
2168
+ const params = this.buildTransactionFilterParams(filters);
1831
2169
  if (filters.page !== void 0) params.set("page", String(filters.page));
1832
2170
  if (filters.perPage !== void 0) params.set("per_page", String(filters.perPage));
1833
2171
  const queryString = params.toString();
@@ -1835,6 +2173,27 @@ var EReportingEndpoint = class {
1835
2173
  const response = await this.sendRequest("GET", url);
1836
2174
  return ComplianceTransactionPage.fromResponse(await this.parseJsonResponse(response));
1837
2175
  }
2176
+ /**
2177
+ * All transactions matching the filters as raw CSV for bookkeeping
2178
+ * (semicolon-separated) — the same filters as listTransactions() without
2179
+ * pagination. Columns: invoice_number, internal_reference, invoice_date,
2180
+ * due_date, country, transaction_type, document_type, state, delivery_state,
2181
+ * buyer_rejected, rejection_reason, counterparty_name, counterparty_country,
2182
+ * counterparty_vat_number, currency, subtotal, tax_amount, total, eur_rate,
2183
+ * eur_rate_date, eur_subtotal, eur_tax_amount, eur_total, provider_invoice_id,
2184
+ * created_at. The eur_* columns hold the ECB reference conversion for non-EUR
2185
+ * invoices (empty for EUR). Max 50,000 rows server-side. The body is returned
2186
+ * verbatim, a UTF-8 BOM included when the API sends one.
2187
+ */
2188
+ async exportTransactionsCsv(filters = {}) {
2189
+ const queryString = this.buildTransactionFilterParams(filters).toString();
2190
+ const url = `${this.baseUrl}/compliance/transactions/export.csv${queryString ? `?${queryString}` : ""}`;
2191
+ const response = await this.sendDownloadRequest(url, "text/csv, application/json");
2192
+ if (!response.ok) {
2193
+ await this.parseJsonResponse(response);
2194
+ }
2195
+ return new TextDecoder("utf-8", { ignoreBOM: true }).decode(await response.arrayBuffer());
2196
+ }
1838
2197
  /** Get a single transaction by id (includes its tax report when one exists). */
1839
2198
  async getTransaction(id) {
1840
2199
  this.validateId(id, "id");
@@ -1850,6 +2209,8 @@ var EReportingEndpoint = class {
1850
2209
  if (input.invoiceLines !== void 0) this.validateInvoiceLines(input.invoiceLines);
1851
2210
  this.validateOptionalCodes(input);
1852
2211
  this.validateBuyerFields(input);
2212
+ this.validateInternalReference(input.internalReference);
2213
+ this.validateInvoicePdfFilename(input);
1853
2214
  const body = {};
1854
2215
  if (input.transactionType !== void 0) body["transaction_type"] = input.transactionType;
1855
2216
  if (input.invoiceNumber !== void 0) body["invoice_number"] = input.invoiceNumber;
@@ -1884,6 +2245,47 @@ var EReportingEndpoint = class {
1884
2245
  const data = await this.parseJsonResponse(response);
1885
2246
  return ComplianceTransaction.fromArray(data);
1886
2247
  }
2248
+ /**
2249
+ * Download the legal e-invoice document of a sent transaction (e-invoicing,
2250
+ * e.g. the EHF/UBL XML for Norway). Available once `documentUrl` on the
2251
+ * transaction is set.
2252
+ *
2253
+ * Errors: 404 (HttpException) for an unknown transaction; 409 (HttpException)
2254
+ * when no document exists (yet) — e.g. e-reporting, not sent, or the network
2255
+ * has not produced it yet (try again in a few minutes); 502 on provider failure.
2256
+ */
2257
+ async getTransactionDocument(id) {
2258
+ this.validateId(id, "id");
2259
+ const response = await this.sendDownloadRequest(`${this.baseUrl}/compliance/transactions/${id}/document`, "*/*");
2260
+ if (!response.ok) {
2261
+ await this.parseJsonResponse(response);
2262
+ }
2263
+ return {
2264
+ content: new Uint8Array(await response.arrayBuffer()),
2265
+ contentType: response.headers.get("content-type") ?? "application/octet-stream",
2266
+ filename: this.filenameFromDisposition(response.headers.get("content-disposition"))
2267
+ };
2268
+ }
2269
+ /**
2270
+ * Download the invoice as a readable PDF — the seller's attached PDF, or the
2271
+ * provider's rendering of the e-invoice. Available once `pdfUrl` on the
2272
+ * transaction is set.
2273
+ *
2274
+ * Errors: 404 (HttpException) for an unknown transaction; 409 (HttpException)
2275
+ * when no PDF exists (yet); 502 on provider failure.
2276
+ */
2277
+ async getTransactionPdf(id) {
2278
+ this.validateId(id, "id");
2279
+ const response = await this.sendDownloadRequest(`${this.baseUrl}/compliance/transactions/${id}/pdf`, "*/*");
2280
+ if (!response.ok) {
2281
+ await this.parseJsonResponse(response);
2282
+ }
2283
+ return {
2284
+ content: new Uint8Array(await response.arrayBuffer()),
2285
+ contentType: response.headers.get("content-type") ?? "application/octet-stream",
2286
+ filename: this.filenameFromDisposition(response.headers.get("content-disposition"))
2287
+ };
2288
+ }
1887
2289
  /**
1888
2290
  * Bulk-import transactions from a semicolon-separated CSV (one row per invoice
1889
2291
  * line; rows sharing an invoice_number are grouped into one transaction).
@@ -1915,6 +2317,9 @@ var EReportingEndpoint = class {
1915
2317
  * months and a monthly interval.
1916
2318
  */
1917
2319
  async getRevenueStatistics(filters = {}) {
2320
+ if (filters.complianceEnrollmentId !== void 0) {
2321
+ this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
2322
+ }
1918
2323
  if (filters.interval !== void 0 && !INTERVALS.includes(filters.interval)) {
1919
2324
  throw new TaxoraException(
1920
2325
  `Invalid statistics interval "${String(filters.interval)}". Expected one of: ${INTERVALS.join(", ")}.`
@@ -1926,12 +2331,42 @@ var EReportingEndpoint = class {
1926
2331
  if (filters.interval !== void 0) params.set("interval", filters.interval);
1927
2332
  if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
1928
2333
  if (filters.state !== void 0) params.set("state", filters.state);
2334
+ if (filters.complianceEnrollmentId !== void 0) {
2335
+ params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
2336
+ }
1929
2337
  const queryString = params.toString();
1930
2338
  const url = `${this.baseUrl}/compliance/revenue-statistics${queryString ? `?${queryString}` : ""}`;
1931
2339
  const response = await this.sendRequest("GET", url);
1932
2340
  const data = await this.parseJsonResponse(response);
1933
2341
  return RevenueStatistics.fromArray(data);
1934
2342
  }
2343
+ /**
2344
+ * Net and VAT per month, currency and tax rate as raw CSV (semicolon-separated,
2345
+ * computed from the invoice lines) — for reconciling the reported figures with
2346
+ * your VAT return. Same filters as getRevenueStatistics() (without
2347
+ * `interval`); defaults to the last 12 months. The body is returned verbatim,
2348
+ * a UTF-8 BOM included when the API sends one.
2349
+ */
2350
+ async exportRevenueTaxRatesCsv(filters = {}) {
2351
+ if (filters.complianceEnrollmentId !== void 0) {
2352
+ this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
2353
+ }
2354
+ const params = new URLSearchParams();
2355
+ if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
2356
+ if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
2357
+ if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
2358
+ if (filters.state !== void 0) params.set("state", filters.state);
2359
+ if (filters.complianceEnrollmentId !== void 0) {
2360
+ params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
2361
+ }
2362
+ const queryString = params.toString();
2363
+ const url = `${this.baseUrl}/compliance/revenue-statistics/tax-rates.csv${queryString ? `?${queryString}` : ""}`;
2364
+ const response = await this.sendDownloadRequest(url, "text/csv, application/json");
2365
+ if (!response.ok) {
2366
+ await this.parseJsonResponse(response);
2367
+ }
2368
+ return new TextDecoder("utf-8", { ignoreBOM: true }).decode(await response.arrayBuffer());
2369
+ }
1935
2370
  /**
1936
2371
  * The canonical VAT rates & DGFiP tax categories for a reporting country
1937
2372
  * (the seller's reporting-country rates, not the counterparty's). Falls back
@@ -1946,12 +2381,19 @@ var EReportingEndpoint = class {
1946
2381
  const data = await this.parseJsonResponse(response);
1947
2382
  return VatRates.fromArray(data);
1948
2383
  }
1949
- /** Paginated list of the company's tax reports (newest first), optionally filtered by state. */
1950
- async listTaxReports(page = 1, perPage = 25, state) {
2384
+ /**
2385
+ * Paginated list of the company's tax reports (newest first), optionally
2386
+ * filtered by state and by country (2-letter ISO code, case-insensitive).
2387
+ */
2388
+ async listTaxReports(page = 1, perPage = 25, state, country) {
2389
+ if (country !== void 0 && !COUNTRY_REGEX.test(country)) {
2390
+ throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
2391
+ }
1951
2392
  const params = new URLSearchParams();
1952
2393
  params.set("page", String(page));
1953
2394
  params.set("per_page", String(perPage));
1954
2395
  if (state !== void 0) params.set("state", state);
2396
+ if (country !== void 0) params.set("country", country.toUpperCase());
1955
2397
  const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/tax-reports?${params.toString()}`);
1956
2398
  return ComplianceTaxReportPage.fromResponse(await this.parseJsonResponse(response));
1957
2399
  }
@@ -1993,8 +2435,177 @@ var EReportingEndpoint = class {
1993
2435
  await this.parseJsonResponse(response);
1994
2436
  }
1995
2437
  // ---------------------------------------------------------------------
2438
+ // Self-service plans (Stripe) — not gated by compliance access
2439
+ // ---------------------------------------------------------------------
2440
+ /**
2441
+ * Bookable compliance plans per country (net EUR prices), every country
2442
+ * Taxora reaches, and which services the company has unlocked. Works for
2443
+ * companies without compliance access.
2444
+ */
2445
+ async getOfferings() {
2446
+ const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/offerings`);
2447
+ return ComplianceOfferings.fromArray(await this.parseJsonResponse(response));
2448
+ }
2449
+ /**
2450
+ * Start a Stripe Checkout for a plan (see getOfferings() — `checkoutAvailable`).
2451
+ * Open the returned `url` in the browser. After payment Stripe redirects to
2452
+ * the Taxora portal, which activates the plan; call confirmCheckout() with the
2453
+ * session id to activate it from your side (idempotent).
2454
+ *
2455
+ * Errors: 422 (ValidationException) for an unknown or contact-only plan or a
2456
+ * plan that is already active; 502 (HttpException) on a Stripe error.
2457
+ */
2458
+ async createCheckout(country, plan) {
2459
+ if (!COUNTRY_REGEX.test(country)) {
2460
+ throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
2461
+ }
2462
+ if (plan.trim() === "" || plan.length > 30) {
2463
+ throw new TaxoraException("plan must be a non-empty plan key of at most 30 characters.");
2464
+ }
2465
+ const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/checkout`, {
2466
+ country: country.toUpperCase(),
2467
+ plan
2468
+ });
2469
+ const data = await this.parseJsonResponse(response);
2470
+ return { id: String(data["id"] ?? ""), url: String(data["url"] ?? "") };
2471
+ }
2472
+ /** Confirm a finished Stripe Checkout and activate its plan. Idempotent. */
2473
+ async confirmCheckout(sessionId) {
2474
+ if (sessionId.trim() === "" || sessionId.length > 255) {
2475
+ throw new TaxoraException("sessionId must be a non-empty string of at most 255 characters.");
2476
+ }
2477
+ const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/checkout/confirm`, {
2478
+ session_id: sessionId
2479
+ });
2480
+ const data = await this.parseJsonResponse(response);
2481
+ const str = (value) => typeof value === "string" ? value : null;
2482
+ return {
2483
+ active: data["active"] === true,
2484
+ country: str(data["country"]),
2485
+ service: str(data["service"]),
2486
+ plan: str(data["plan"]),
2487
+ status: str(data["status"])
2488
+ };
2489
+ }
2490
+ /**
2491
+ * URL of the Stripe billing portal for the company's compliance plans
2492
+ * (invoices, payment method, cancellation). The portal returns to the Taxora
2493
+ * portal. 404 (HttpException) when no plan was bought via Stripe.
2494
+ */
2495
+ async createBillingPortalSession() {
2496
+ const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/billing-portal`);
2497
+ const data = await this.parseJsonResponse(response);
2498
+ return String(data["url"] ?? "");
2499
+ }
2500
+ // ---------------------------------------------------------------------
2501
+ // Notification emails
2502
+ // ---------------------------------------------------------------------
2503
+ /**
2504
+ * The company's opt-in e-reporting / e-invoicing emails: recipients, language,
2505
+ * the "buyer not on Peppol" email and the digest. Readable by every member.
2506
+ */
2507
+ async getNotificationSettings() {
2508
+ const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/notification-settings`);
2509
+ return this.toNotificationSettings(await this.parseJsonResponse(response));
2510
+ }
2511
+ /**
2512
+ * Change the company's e-reporting / e-invoicing emails; only the provided
2513
+ * fields change. `notOnPeppol` only reports invoices held back after it was
2514
+ * switched on.
2515
+ *
2516
+ * Errors: 422 (ValidationException) when an email is switched on without any
2517
+ * recipient; 403 (HttpException, body code `admin_only` or `read_only_role`)
2518
+ * for users who are not company admins.
2519
+ */
2520
+ async updateNotificationSettings(input) {
2521
+ const body = {};
2522
+ if (input.recipients !== void 0) {
2523
+ if (!Array.isArray(input.recipients)) {
2524
+ throw new TaxoraException("recipients must be an array of email addresses.");
2525
+ }
2526
+ if (input.recipients.length > NOTIFICATION_MAX_RECIPIENTS) {
2527
+ throw new TaxoraException(`recipients must not contain more than ${NOTIFICATION_MAX_RECIPIENTS} entries.`);
2528
+ }
2529
+ body["recipients"] = input.recipients.map((recipient, index) => {
2530
+ const email = typeof recipient === "string" ? recipient.trim() : recipient;
2531
+ this.validateEmail(email, `recipients[${index}]`);
2532
+ if (email.length > 191) {
2533
+ throw new TaxoraException(`recipients[${index}] must not exceed 191 characters.`);
2534
+ }
2535
+ return email;
2536
+ });
2537
+ }
2538
+ if (input.language !== void 0) {
2539
+ if (!NOTIFICATION_LANGUAGES.includes(input.language)) {
2540
+ throw new TaxoraException(
2541
+ `Invalid language "${String(input.language)}". Expected one of: ${NOTIFICATION_LANGUAGES.join(", ")}.`
2542
+ );
2543
+ }
2544
+ body["language"] = input.language;
2545
+ }
2546
+ if (input.notOnPeppol !== void 0) {
2547
+ if (typeof input.notOnPeppol !== "boolean") {
2548
+ throw new TaxoraException("notOnPeppol must be a boolean.");
2549
+ }
2550
+ body["not_on_peppol"] = input.notOnPeppol;
2551
+ }
2552
+ if (input.digest !== void 0) {
2553
+ if (!NOTIFICATION_DIGESTS.includes(input.digest)) {
2554
+ throw new TaxoraException(
2555
+ `Invalid digest "${String(input.digest)}". Expected one of: ${NOTIFICATION_DIGESTS.join(", ")}.`
2556
+ );
2557
+ }
2558
+ body["digest"] = input.digest;
2559
+ }
2560
+ if (Object.keys(body).length === 0) {
2561
+ throw new TaxoraException("updateNotificationSettings requires at least one field to update.");
2562
+ }
2563
+ const response = await this.sendRequest("PUT", `${this.baseUrl}/compliance/notification-settings`, body);
2564
+ return this.toNotificationSettings(await this.parseJsonResponse(response));
2565
+ }
2566
+ toNotificationSettings(data) {
2567
+ const recipients = Array.isArray(data["recipients"]) ? data["recipients"].filter((r) => typeof r === "string" && r !== "") : [];
2568
+ const digest = data["digest"];
2569
+ return {
2570
+ recipients,
2571
+ language: data["language"] === "en" ? "en" : "de",
2572
+ notOnPeppol: data["not_on_peppol"] === true,
2573
+ digest: digest === "daily" || digest === "weekly" ? digest : "off",
2574
+ digestSentAt: typeof data["digest_sent_at"] === "string" ? data["digest_sent_at"] : null
2575
+ };
2576
+ }
2577
+ // ---------------------------------------------------------------------
1996
2578
  // Input validation (fail fast, before any request is sent)
1997
2579
  // ---------------------------------------------------------------------
2580
+ /** Validated transaction-list filters as query params (shared by listTransactions and exportTransactionsCsv). */
2581
+ buildTransactionFilterParams(filters) {
2582
+ if (filters.complianceEnrollmentId !== void 0) {
2583
+ this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
2584
+ }
2585
+ if (filters.country !== void 0 && !COUNTRY_REGEX.test(filters.country)) {
2586
+ throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
2587
+ }
2588
+ if (filters.search !== void 0 && filters.search.length > 100) {
2589
+ throw new TaxoraException("search must not exceed 100 characters.");
2590
+ }
2591
+ this.validateInternalReference(filters.internalReference);
2592
+ if (filters.providerState !== void 0 && !/^[a-z_]{1,30}$/.test(filters.providerState)) {
2593
+ throw new TaxoraException('providerState must be 1-30 lowercase letters or underscores (e.g. "refused").');
2594
+ }
2595
+ const params = new URLSearchParams();
2596
+ if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
2597
+ if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
2598
+ if (filters.state !== void 0) params.set("state", filters.state);
2599
+ if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
2600
+ if (filters.complianceEnrollmentId !== void 0) {
2601
+ params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
2602
+ }
2603
+ if (filters.country !== void 0) params.set("country", filters.country.toUpperCase());
2604
+ if (filters.search !== void 0) params.set("search", filters.search);
2605
+ if (filters.internalReference !== void 0) params.set("internal_reference", filters.internalReference);
2606
+ if (filters.providerState !== void 0) params.set("provider_state", filters.providerState);
2607
+ return params;
2608
+ }
1998
2609
  validateEnrollmentInput(input) {
1999
2610
  if (input.siret === void 0 && input.siren === void 0) {
2000
2611
  throw new TaxoraException("Either siret or siren is required.");
@@ -2122,6 +2733,20 @@ var EReportingEndpoint = class {
2122
2733
  }
2123
2734
  });
2124
2735
  }
2736
+ validateInvoicePdfFilename(input) {
2737
+ if (input.invoicePdfFilename === void 0) return;
2738
+ if (input.invoicePdfFilename.length > 120) {
2739
+ throw new TaxoraException("invoicePdfFilename must not exceed 120 characters.");
2740
+ }
2741
+ if (input.invoicePdf === void 0) {
2742
+ throw new TaxoraException("invoicePdfFilename requires invoicePdf.");
2743
+ }
2744
+ }
2745
+ validateInternalReference(internalReference) {
2746
+ if (internalReference !== void 0 && internalReference.length > 100) {
2747
+ throw new TaxoraException("internalReference must not exceed 100 characters.");
2748
+ }
2749
+ }
2125
2750
  validateOptionalCodes(input) {
2126
2751
  if (input.currency !== void 0 && input.currency.length !== 3) {
2127
2752
  throw new TaxoraException("currency must be a 3-character ISO 4217 code.");
@@ -2203,6 +2828,29 @@ var EReportingEndpoint = class {
2203
2828
  if (input.amendedNumber !== void 0) body["amended_number"] = input.amendedNumber;
2204
2829
  if (input.amendedDate !== void 0) body["amended_date"] = this.formatDate(input.amendedDate);
2205
2830
  if (input.extraInfo !== void 0) body["extra_info"] = input.extraInfo;
2831
+ if (input.internalReference !== void 0) body["internal_reference"] = input.internalReference;
2832
+ if (input.invoicePdf !== void 0) body["invoice_pdf"] = this.encodeInvoicePdf(input.invoicePdf);
2833
+ if (input.invoicePdfFilename !== void 0) body["invoice_pdf_filename"] = input.invoicePdfFilename;
2834
+ }
2835
+ /** Bytes → base64 (validated as a PDF of at most 10 MB); strings are taken as already base64. */
2836
+ encodeInvoicePdf(pdf) {
2837
+ if (typeof pdf === "string") {
2838
+ if (pdf.trim() === "") {
2839
+ throw new TaxoraException("invoicePdf must not be empty.");
2840
+ }
2841
+ return pdf;
2842
+ }
2843
+ const bytes = pdf instanceof Uint8Array ? pdf : new Uint8Array(pdf);
2844
+ if (bytes.byteLength === 0) {
2845
+ throw new TaxoraException("invoicePdf must not be empty.");
2846
+ }
2847
+ if (bytes.byteLength > INVOICE_PDF_MAX_BYTES) {
2848
+ throw new TaxoraException("invoicePdf must not exceed 10 MB.");
2849
+ }
2850
+ if (!INVOICE_PDF_MAGIC.every((byte, index) => bytes[index] === byte)) {
2851
+ throw new TaxoraException('invoicePdf must be a PDF file (content must start with "%PDF-").');
2852
+ }
2853
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64");
2206
2854
  }
2207
2855
  // ---------------------------------------------------------------------
2208
2856
  // HTTP plumbing (kept in sync with SmartEnrichmentEndpoint)
@@ -2226,6 +2874,30 @@ var EReportingEndpoint = class {
2226
2874
  const send = () => this.httpClient.request(method, url, options);
2227
2875
  return method === "GET" ? withResponseRetries(this.retryPolicy, "e-reporting request", send) : send();
2228
2876
  }
2877
+ /** GET for a non-JSON download (CSV / document): no JSON Content-Type, retried like other GETs. */
2878
+ async sendDownloadRequest(url, accept) {
2879
+ const headers = this.buildHeaders(false);
2880
+ headers["Accept"] = accept;
2881
+ return withResponseRetries(
2882
+ this.retryPolicy,
2883
+ "e-reporting download",
2884
+ () => this.httpClient.request("GET", url, { headers })
2885
+ );
2886
+ }
2887
+ /** `attachment; filename="x.xml"` (or RFC 5987 `filename*=UTF-8''x.xml`) → "x.xml". */
2888
+ filenameFromDisposition(header) {
2889
+ if (header === null) return null;
2890
+ const extended = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/.exec(header);
2891
+ if (extended?.[1] !== void 0) {
2892
+ try {
2893
+ return decodeURIComponent(extended[1].trim());
2894
+ } catch {
2895
+ }
2896
+ }
2897
+ const plain = /filename\s*=\s*"([^"]*)"|filename\s*=\s*([^;]+)/.exec(header);
2898
+ const name = (plain?.[1] ?? plain?.[2])?.trim();
2899
+ return name !== void 0 && name !== "" ? name : null;
2900
+ }
2229
2901
  /** Multipart upload: Content-Type is left to fetch so the boundary is set correctly. */
2230
2902
  async sendMultipartRequest(method, url, form) {
2231
2903
  return this.httpClient.request(method, url, { headers: this.buildHeaders(false), body: form });
@@ -2807,13 +3479,13 @@ var SmartEnrichmentHistoryPage = class _SmartEnrichmentHistoryPage {
2807
3479
  };
2808
3480
 
2809
3481
  // src/dto/SmartEnrichmentStatistics.ts
2810
- function asString9(value, fallback = "") {
3482
+ function asString11(value, fallback = "") {
2811
3483
  return typeof value === "string" ? value : fallback;
2812
3484
  }
2813
- function asNumber6(value) {
3485
+ function asNumber7(value) {
2814
3486
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
2815
3487
  }
2816
- function asRecord2(value) {
3488
+ function asRecord4(value) {
2817
3489
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
2818
3490
  }
2819
3491
  function asRecords2(value) {
@@ -2836,39 +3508,39 @@ var SmartEnrichmentStatistics = class _SmartEnrichmentStatistics {
2836
3508
  byOutcome;
2837
3509
  confidenceBuckets;
2838
3510
  static fromArray(data) {
2839
- const range = asRecord2(data["range"]);
2840
- const totals = asRecord2(data["totals"]);
3511
+ const range = asRecord4(data["range"]);
3512
+ const totals = asRecord4(data["totals"]);
2841
3513
  const timeSeries = asRecords2(data["time_series"]).map((row) => ({
2842
- bucket: asString9(row["bucket"]),
2843
- jobs: asNumber6(row["jobs"]),
2844
- items: asNumber6(row["items"]),
2845
- found: asNumber6(row["found"])
3514
+ bucket: asString11(row["bucket"]),
3515
+ jobs: asNumber7(row["jobs"]),
3516
+ items: asNumber7(row["items"]),
3517
+ found: asNumber7(row["found"])
2846
3518
  }));
2847
3519
  const bySource = asRecords2(data["by_source"]).map((row) => ({
2848
- source: asString9(row["source"]),
2849
- jobs: asNumber6(row["jobs"]),
2850
- found: asNumber6(row["found"])
3520
+ source: asString11(row["source"]),
3521
+ jobs: asNumber7(row["jobs"]),
3522
+ found: asNumber7(row["found"])
2851
3523
  }));
2852
3524
  const byOutcome = asRecords2(data["by_outcome"]).map((row) => ({
2853
- outcome: asString9(row["outcome"]),
2854
- count: asNumber6(row["count"])
3525
+ outcome: asString11(row["outcome"]),
3526
+ count: asNumber7(row["count"])
2855
3527
  }));
2856
3528
  const confidenceBuckets = asRecords2(data["confidence_buckets"]).map((row) => ({
2857
- bucket: asString9(row["bucket"]),
2858
- count: asNumber6(row["count"])
3529
+ bucket: asString11(row["bucket"]),
3530
+ count: asNumber7(row["count"])
2859
3531
  }));
2860
3532
  return new _SmartEnrichmentStatistics(
2861
3533
  {
2862
- dateFrom: asString9(range["date_from"]),
2863
- dateTo: asString9(range["date_to"]),
2864
- interval: asString9(range["interval"])
3534
+ dateFrom: asString11(range["date_from"]),
3535
+ dateTo: asString11(range["date_to"]),
3536
+ interval: asString11(range["interval"])
2865
3537
  },
2866
3538
  {
2867
- jobs: asNumber6(totals["jobs"]),
2868
- items: asNumber6(totals["items"]),
2869
- found: asNumber6(totals["found"]),
2870
- foundRate: asNumber6(totals["found_rate"]),
2871
- avgConfidence: asNumber6(totals["avg_confidence"])
3539
+ jobs: asNumber7(totals["jobs"]),
3540
+ items: asNumber7(totals["items"]),
3541
+ found: asNumber7(totals["found"]),
3542
+ foundRate: asNumber7(totals["found_rate"]),
3543
+ avgConfidence: asNumber7(totals["avg_confidence"])
2872
3544
  },
2873
3545
  timeSeries,
2874
3546
  bySource,
@@ -4148,7 +4820,7 @@ var AuthRetryHttpClient = class {
4148
4820
  };
4149
4821
 
4150
4822
  // src/version.ts
4151
- var SDK_VERSION = "1.8.0";
4823
+ var SDK_VERSION = "1.9.0";
4152
4824
 
4153
4825
  // src/http/SdkVersionHttpClient.ts
4154
4826
  var SDK_VERSION_HEADER = "X-Taxora-SDK-Version";
@@ -4175,6 +4847,7 @@ var TaxoraClient = class {
4175
4847
  company;
4176
4848
  smartEnrichment;
4177
4849
  eReporting;
4850
+ billing;
4178
4851
  baseUrl;
4179
4852
  constructor(options) {
4180
4853
  const environment = options.environment ?? Environment.SANDBOX;
@@ -4195,6 +4868,7 @@ var TaxoraClient = class {
4195
4868
  retryPolicy
4196
4869
  );
4197
4870
  this.eReporting = new EReportingEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient, retryPolicy);
4871
+ this.billing = new BillingEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient, retryPolicy);
4198
4872
  }
4199
4873
  };
4200
4874
 
@@ -4334,18 +5008,25 @@ function toBytes(rawBody) {
4334
5008
  "invalid_body"
4335
5009
  );
4336
5010
  }
5011
+
5012
+ // src/webhooks/WebhookEvent.ts
5013
+ function isTransactionBuyerRejected(object) {
5014
+ return object.buyer_rejected === true;
5015
+ }
4337
5016
  // Annotate the CommonJS export names for ESM import in node:
4338
5017
  0 && (module.exports = {
4339
5018
  ApiVersion,
4340
5019
  AuthEndpoint,
4341
5020
  AuthRetryHttpClient,
4342
5021
  AuthenticationException,
5022
+ BillingEndpoint,
4343
5023
  CompanyAddress,
4344
5024
  CompanyEndpoint,
4345
5025
  ComplianceDocumentType,
4346
5026
  ComplianceEnrollment,
4347
5027
  ComplianceEnrollmentPage,
4348
5028
  ComplianceEnrollmentStatus,
5029
+ ComplianceOfferings,
4349
5030
  ComplianceService,
4350
5031
  ComplianceTaxReport,
4351
5032
  ComplianceTaxReportPage,
@@ -4389,6 +5070,8 @@ function toBytes(rawBody) {
4389
5070
  TaxoraClientFactory,
4390
5071
  TaxoraException,
4391
5072
  Token,
5073
+ UsageSummary,
5074
+ UsageSummaryPage,
4392
5075
  ValidationException,
4393
5076
  VatCertificateExport,
4394
5077
  VatCollection,
@@ -4417,6 +5100,7 @@ function toBytes(rawBody) {
4417
5100
  generateWebhookSignatureHeader,
4418
5101
  getBaseUrl,
4419
5102
  getFailedVatStates,
5103
+ isTransactionBuyerRejected,
4420
5104
  parseLocalTaxNumbersCsv,
4421
5105
  parseWebhookSignatureHeader,
4422
5106
  toComplianceDocumentType,