@taxora/sdk 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to `@taxora/sdk` are documented here. Versions follow [SemVer](https://semver.org/).
4
4
 
5
+ ## [1.5.0] — 2026-10-22
6
+
7
+ ### Added
8
+
9
+ - **Smart Enrichment: `sourceUrl` and `registeredOwner`** on `SmartEnrichmentResource`. `sourceUrl` is the page
10
+ the VAT number was read from (usually the company's Impressum; only http(s) addresses are accepted).
11
+ `registeredOwner` names the person the tax authority has the VAT ID under when that is not the trading name —
12
+ typical for a German sole proprietorship (e.K.). `sourceUrls` lists every page the number was read from,
13
+ `sourceUrl` first (each research pass that found the same number contributes its page).
14
+
15
+ ### Changed
16
+
17
+ - Bundled OpenAPI specs (`resources/`) refreshed from the current API.
18
+
19
+ ## [1.4.0] — 2026-10-21
20
+
21
+ ### Added
22
+
23
+ - **Smart Enrichment: rejected VAT candidates.** `SmartEnrichmentResource.rejectedCandidates` lists VAT numbers
24
+ a `not_found` lookup DID find but the official check threw out, each with a `reason`
25
+ (`SmartEnrichmentRejectionReason`: `vat_invalid`, `name_mismatch`, `unbound`, `unverified`, `rejected`;
26
+ unknown values map to `unknown`). Lets you tell "found one, it is invalid" apart from "found nothing".
27
+ Plus `hasRejectedCandidates()`, `toSmartEnrichmentRejectionReason()` and
28
+ `describeSmartEnrichmentRejectionReason()`.
29
+
30
+ ### Changed
31
+
32
+ - Bundled OpenAPI specs (`resources/`) refreshed from the current API.
33
+
5
34
  ## [1.3.0] — 2026-10-13
6
35
 
7
36
  ### Added
package/README.md CHANGED
@@ -363,6 +363,20 @@ if (quality && quality.warnings.length > 0) {
363
363
  console.log(quality.warnings.join(', '), '→', quality.derivedPlace);
364
364
  }
365
365
 
366
+ // Where the number came from, and who it is registered to. `sourceUrl` is the page it was read
367
+ // from (usually the Impressum). `registeredOwner` is set when the tax authority has the VAT ID
368
+ // under a person rather than the trading name — a German e.K. — and confirmed it for them.
369
+ console.log(result?.sourceUrl ?? '—'); // e.g. 'https://example.de/impressum'
370
+ console.log(result?.sourceUrls.join(', ')); // every page it was found on, main one first
371
+ console.log(result?.registeredOwner ?? '—'); // e.g. 'Kevin Seibel'
372
+
373
+ // 'not_found' doesn't always mean nothing turned up. When the research found a VAT number but
374
+ // the official check threw it out (e.g. the tax authority reports it as invalid), the number
375
+ // and the reason are in `rejectedCandidates` — no need to re-check it yourself.
376
+ for (const candidate of result?.rejectedCandidates ?? []) {
377
+ console.log(candidate.vatNumber, candidate.reason); // e.g. 'vat_invalid'
378
+ }
379
+
366
380
  // Bulk lookup (always async → webhook + polling)
367
381
  // The batch-level mode applies to every row; a row carrying its own `mode` overrides it,
368
382
  // so you can pay for 'complex' on just the rows that need it.
package/dist/index.cjs CHANGED
@@ -62,6 +62,7 @@ __export(index_exports, {
62
62
  SmartEnrichmentHistoryRow: () => SmartEnrichmentHistoryRow,
63
63
  SmartEnrichmentJob: () => SmartEnrichmentJob,
64
64
  SmartEnrichmentMode: () => SmartEnrichmentMode,
65
+ SmartEnrichmentRejectionReason: () => SmartEnrichmentRejectionReason,
65
66
  SmartEnrichmentResource: () => SmartEnrichmentResource,
66
67
  SmartEnrichmentStatistics: () => SmartEnrichmentStatistics,
67
68
  SmartEnrichmentStatus: () => SmartEnrichmentStatus,
@@ -91,6 +92,7 @@ __export(index_exports, {
91
92
  describeComplianceTransactionType: () => describeComplianceTransactionType,
92
93
  describePeppolLookupStatus: () => describePeppolLookupStatus,
93
94
  describeSmartEnrichmentMode: () => describeSmartEnrichmentMode,
95
+ describeSmartEnrichmentRejectionReason: () => describeSmartEnrichmentRejectionReason,
94
96
  describeSmartEnrichmentStatus: () => describeSmartEnrichmentStatus,
95
97
  describeVatState: () => describeVatState,
96
98
  generateWebhookSignatureHeader: () => generateWebhookSignatureHeader,
@@ -105,6 +107,7 @@ __export(index_exports, {
105
107
  toComplianceTransactionType: () => toComplianceTransactionType,
106
108
  toPeppolLookupStatus: () => toPeppolLookupStatus,
107
109
  toSmartEnrichmentMode: () => toSmartEnrichmentMode,
110
+ toSmartEnrichmentRejectionReason: () => toSmartEnrichmentRejectionReason,
108
111
  toSmartEnrichmentStatus: () => toSmartEnrichmentStatus,
109
112
  verifyWebhookSignature: () => verifyWebhookSignature
110
113
  });
@@ -2336,6 +2339,43 @@ function describeSmartEnrichmentMode(mode) {
2336
2339
  return DESCRIPTIONS8[mode];
2337
2340
  }
2338
2341
 
2342
+ // src/enums/SmartEnrichmentRejectionReason.ts
2343
+ var SmartEnrichmentRejectionReason = {
2344
+ /** The tax authority reports the number as not (or no longer) valid. */
2345
+ VAT_INVALID: "vat_invalid",
2346
+ /** The number is valid, but registered to a different company. */
2347
+ NAME_MISMATCH: "name_mismatch",
2348
+ /** The number could not be tied to the requested company. */
2349
+ UNBOUND: "unbound",
2350
+ /** The number could not be checked against the tax authority. */
2351
+ UNVERIFIED: "unverified",
2352
+ /** Rejected for another reason. */
2353
+ REJECTED: "rejected",
2354
+ /** A reason this SDK version does not know yet. */
2355
+ UNKNOWN: "unknown"
2356
+ };
2357
+ var VALUES9 = Object.values(SmartEnrichmentRejectionReason);
2358
+ function toSmartEnrichmentRejectionReason(value) {
2359
+ if (typeof value === "string") {
2360
+ const normalized = value.trim().toLowerCase();
2361
+ if (VALUES9.includes(normalized)) {
2362
+ return normalized;
2363
+ }
2364
+ }
2365
+ return SmartEnrichmentRejectionReason.UNKNOWN;
2366
+ }
2367
+ var DESCRIPTIONS9 = {
2368
+ [SmartEnrichmentRejectionReason.VAT_INVALID]: "The tax authority reports the VAT number as invalid.",
2369
+ [SmartEnrichmentRejectionReason.NAME_MISMATCH]: "The VAT number is registered to a different company.",
2370
+ [SmartEnrichmentRejectionReason.UNBOUND]: "The VAT number could not be tied to the requested company.",
2371
+ [SmartEnrichmentRejectionReason.UNVERIFIED]: "The VAT number could not be verified with the tax authority.",
2372
+ [SmartEnrichmentRejectionReason.REJECTED]: "The VAT number was not confirmed.",
2373
+ [SmartEnrichmentRejectionReason.UNKNOWN]: "Unknown rejection reason."
2374
+ };
2375
+ function describeSmartEnrichmentRejectionReason(reason) {
2376
+ return DESCRIPTIONS9[reason];
2377
+ }
2378
+
2339
2379
  // src/enums/SmartEnrichmentStatus.ts
2340
2380
  var SmartEnrichmentStatus = {
2341
2381
  FOUND: "found",
@@ -2347,17 +2387,17 @@ var SmartEnrichmentStatus = {
2347
2387
  FAILED: "failed",
2348
2388
  UNKNOWN: "unknown"
2349
2389
  };
2350
- var VALUES9 = Object.values(SmartEnrichmentStatus);
2390
+ var VALUES10 = Object.values(SmartEnrichmentStatus);
2351
2391
  function toSmartEnrichmentStatus(value) {
2352
2392
  if (typeof value === "string") {
2353
2393
  const normalized = value.trim().toLowerCase();
2354
- if (VALUES9.includes(normalized)) {
2394
+ if (VALUES10.includes(normalized)) {
2355
2395
  return normalized;
2356
2396
  }
2357
2397
  }
2358
2398
  return SmartEnrichmentStatus.UNKNOWN;
2359
2399
  }
2360
- var DESCRIPTIONS9 = {
2400
+ var DESCRIPTIONS10 = {
2361
2401
  [SmartEnrichmentStatus.FOUND]: "A VAT number was resolved and confirmed.",
2362
2402
  [SmartEnrichmentStatus.NO_VAT_EXISTS]: "The company was identified but has no VAT number.",
2363
2403
  [SmartEnrichmentStatus.NOT_FOUND]: "No sufficiently-confident match could be resolved.",
@@ -2368,12 +2408,30 @@ var DESCRIPTIONS9 = {
2368
2408
  [SmartEnrichmentStatus.UNKNOWN]: "Unknown status."
2369
2409
  };
2370
2410
  function describeSmartEnrichmentStatus(status) {
2371
- return DESCRIPTIONS9[status];
2411
+ return DESCRIPTIONS10[status];
2372
2412
  }
2373
2413
 
2374
2414
  // src/dto/SmartEnrichmentResource.ts
2415
+ function toRejectedCandidates(value) {
2416
+ if (!Array.isArray(value)) {
2417
+ return [];
2418
+ }
2419
+ const candidates = [];
2420
+ for (const entry of value) {
2421
+ if (typeof entry !== "object" || entry === null) {
2422
+ continue;
2423
+ }
2424
+ const record = entry;
2425
+ const vatNumber = typeof record["vatNumber"] === "string" ? record["vatNumber"].trim() : "";
2426
+ if (vatNumber === "") {
2427
+ continue;
2428
+ }
2429
+ candidates.push({ vatNumber, reason: toSmartEnrichmentRejectionReason(record["reason"]) });
2430
+ }
2431
+ return candidates;
2432
+ }
2375
2433
  var SmartEnrichmentResource = class _SmartEnrichmentResource {
2376
- constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0) {
2434
+ constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0, rejectedCandidates = [], sourceUrl = void 0, registeredOwner = void 0, sourceUrls = []) {
2377
2435
  this.status = status;
2378
2436
  this.vatNumber = vatNumber;
2379
2437
  this.vatType = vatType;
@@ -2385,6 +2443,10 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2385
2443
  this.mode = mode;
2386
2444
  this.providerVerdicts = providerVerdicts;
2387
2445
  this.addressQuality = addressQuality;
2446
+ this.rejectedCandidates = rejectedCandidates;
2447
+ this.sourceUrl = sourceUrl;
2448
+ this.registeredOwner = registeredOwner;
2449
+ this.sourceUrls = sourceUrls;
2388
2450
  }
2389
2451
  status;
2390
2452
  vatNumber;
@@ -2397,11 +2459,26 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2397
2459
  mode;
2398
2460
  providerVerdicts;
2399
2461
  addressQuality;
2462
+ rejectedCandidates;
2463
+ sourceUrl;
2464
+ registeredOwner;
2465
+ sourceUrls;
2466
+ /** True when a VAT number was found but rejected by the official check. */
2467
+ hasRejectedCandidates() {
2468
+ return this.rejectedCandidates.length > 0;
2469
+ }
2400
2470
  static fromArray(data) {
2401
2471
  const str = (key) => {
2402
2472
  const v = data[key];
2403
2473
  return typeof v === "string" ? v : void 0;
2404
2474
  };
2475
+ const text = (key) => {
2476
+ const v = str(key)?.trim();
2477
+ return v ? v : void 0;
2478
+ };
2479
+ const isWebUrl = (value) => typeof value === "string" && /^https?:\/\/\S+$/i.test(value.trim());
2480
+ const url = text("sourceUrl");
2481
+ const urls = data["sourceUrls"];
2405
2482
  const num = (key) => {
2406
2483
  const v = data[key];
2407
2484
  return typeof v === "number" ? v : void 0;
@@ -2419,7 +2496,11 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2419
2496
  str("source"),
2420
2497
  toSmartEnrichmentMode(data["mode"]),
2421
2498
  Array.isArray(verdicts) ? verdicts.filter((v) => typeof v === "object" && v !== null) : [],
2422
- typeof quality === "object" && quality !== null ? quality : void 0
2499
+ typeof quality === "object" && quality !== null ? quality : void 0,
2500
+ toRejectedCandidates(data["rejectedCandidates"]),
2501
+ url && isWebUrl(url) ? url : void 0,
2502
+ text("registeredOwner"),
2503
+ Array.isArray(urls) ? [...new Set(urls.filter(isWebUrl).map((u) => u.trim()))] : []
2423
2504
  );
2424
2505
  }
2425
2506
  toArray() {
@@ -2434,7 +2515,11 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2434
2515
  source: this.source ?? null,
2435
2516
  mode: this.mode ?? null,
2436
2517
  providerVerdicts: this.providerVerdicts,
2437
- addressQuality: this.addressQuality ?? null
2518
+ addressQuality: this.addressQuality ?? null,
2519
+ rejectedCandidates: this.rejectedCandidates.map((c) => ({ vatNumber: c.vatNumber, reason: c.reason })),
2520
+ sourceUrl: this.sourceUrl ?? null,
2521
+ registeredOwner: this.registeredOwner ?? null,
2522
+ sourceUrls: this.sourceUrls
2438
2523
  };
2439
2524
  }
2440
2525
  };
@@ -2973,14 +3058,14 @@ var VatState = {
2973
3058
  function getFailedVatStates() {
2974
3059
  return [VatState.INVALID, VatState.FRAUD];
2975
3060
  }
2976
- var DESCRIPTIONS10 = {
3061
+ var DESCRIPTIONS11 = {
2977
3062
  [VatState.VALID]: "The VAT number is valid and active.",
2978
3063
  [VatState.INVALID]: "The VAT number is invalid or not registered.",
2979
3064
  [VatState.FRAUD]: "The VAT number has been flagged as potentially fraudulent.",
2980
3065
  [VatState.UNKNOWN]: "The VAT number state could not be determined."
2981
3066
  };
2982
3067
  function describeVatState(state) {
2983
- return DESCRIPTIONS10[state];
3068
+ return DESCRIPTIONS11[state];
2984
3069
  }
2985
3070
 
2986
3071
  // src/dto/CompanyAddress.ts
@@ -3712,7 +3797,7 @@ var AuthRetryHttpClient = class {
3712
3797
  };
3713
3798
 
3714
3799
  // src/version.ts
3715
- var SDK_VERSION = "1.3.0";
3800
+ var SDK_VERSION = "1.5.0";
3716
3801
 
3717
3802
  // src/http/SdkVersionHttpClient.ts
3718
3803
  var SDK_VERSION_HEADER = "X-Taxora-SDK-Version";
@@ -3942,6 +4027,7 @@ function toBytes(rawBody) {
3942
4027
  SmartEnrichmentHistoryRow,
3943
4028
  SmartEnrichmentJob,
3944
4029
  SmartEnrichmentMode,
4030
+ SmartEnrichmentRejectionReason,
3945
4031
  SmartEnrichmentResource,
3946
4032
  SmartEnrichmentStatistics,
3947
4033
  SmartEnrichmentStatus,
@@ -3971,6 +4057,7 @@ function toBytes(rawBody) {
3971
4057
  describeComplianceTransactionType,
3972
4058
  describePeppolLookupStatus,
3973
4059
  describeSmartEnrichmentMode,
4060
+ describeSmartEnrichmentRejectionReason,
3974
4061
  describeSmartEnrichmentStatus,
3975
4062
  describeVatState,
3976
4063
  generateWebhookSignatureHeader,
@@ -3985,6 +4072,7 @@ function toBytes(rawBody) {
3985
4072
  toComplianceTransactionType,
3986
4073
  toPeppolLookupStatus,
3987
4074
  toSmartEnrichmentMode,
4075
+ toSmartEnrichmentRejectionReason,
3988
4076
  toSmartEnrichmentStatus,
3989
4077
  verifyWebhookSignature
3990
4078
  });