@taxora/sdk 1.4.0 → 1.6.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,34 @@
2
2
 
3
3
  All notable changes to `@taxora/sdk` are documented here. Versions follow [SemVer](https://semver.org/).
4
4
 
5
+ ## [1.6.0] — 2026-10-22
6
+
7
+ ### Added
8
+
9
+ - **Smart Enrichment: `taxNumber`** — a domestic tax number (e.g. a German Steuernummer) a company's page shows
10
+ instead of a VAT ID. It is not a VAT ID; the lookup stays `not_found`.
11
+ - **Smart Enrichment: the official VAT check behind a found number** — `vatValid`, `aiScore`, `nameMatch`
12
+ (`'ok' | 'mismatch'`, plus `nameMismatch()`), `officialName` and `officialAddress`
13
+ (`SmartEnrichmentOfficialAddress`). Lets you write the register's name and address back into your records.
14
+
15
+ ### Changed
16
+
17
+ - Bundled OpenAPI specs (`resources/`) refreshed from the current API.
18
+
19
+ ## [1.5.0] — 2026-10-22
20
+
21
+ ### Added
22
+
23
+ - **Smart Enrichment: `sourceUrl` and `registeredOwner`** on `SmartEnrichmentResource`. `sourceUrl` is the page
24
+ the VAT number was read from (usually the company's Impressum; only http(s) addresses are accepted).
25
+ `registeredOwner` names the person the tax authority has the VAT ID under when that is not the trading name —
26
+ typical for a German sole proprietorship (e.K.). `sourceUrls` lists every page the number was read from,
27
+ `sourceUrl` first (each research pass that found the same number contributes its page).
28
+
29
+ ### Changed
30
+
31
+ - Bundled OpenAPI specs (`resources/`) refreshed from the current API.
32
+
5
33
  ## [1.4.0] — 2026-10-21
6
34
 
7
35
  ### Added
package/README.md CHANGED
@@ -363,6 +363,24 @@ 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
+ // The official VAT check behind a found number. nameMatch 'mismatch' means the register has the
374
+ // number under a different name — another company, unless `registeredOwner` is set (an e.K. filed
375
+ // under its owner): then write officialName / officialAddress into your own records.
376
+ if (result?.nameMismatch()) {
377
+ console.log(result.officialName, result.officialAddress);
378
+ }
379
+
380
+ // A page that shows a tax number (Steuernummer) under the VAT ID heading is not a VAT ID:
381
+ // the lookup stays 'not_found' and the number comes back as `taxNumber`.
382
+ console.log(result?.taxNumber ?? '—');
383
+
366
384
  // 'not_found' doesn't always mean nothing turned up. When the research found a VAT number but
367
385
  // the official check threw it out (e.g. the tax authority reports it as invalid), the number
368
386
  // and the reason are in `rejectedCandidates` — no need to re-check it yourself.
package/dist/index.cjs CHANGED
@@ -2430,8 +2430,22 @@ function toRejectedCandidates(value) {
2430
2430
  }
2431
2431
  return candidates;
2432
2432
  }
2433
+ function toOfficialAddress(value) {
2434
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2435
+ return void 0;
2436
+ }
2437
+ const record = value;
2438
+ const address = {};
2439
+ for (const key of ["street", "postal_code", "city", "country"]) {
2440
+ const part = typeof record[key] === "string" ? record[key].trim() : "";
2441
+ if (part !== "") {
2442
+ address[key] = part;
2443
+ }
2444
+ }
2445
+ return Object.keys(address).length > 0 ? address : void 0;
2446
+ }
2433
2447
  var SmartEnrichmentResource = class _SmartEnrichmentResource {
2434
- constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0, rejectedCandidates = []) {
2448
+ constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0, rejectedCandidates = [], sourceUrl = void 0, registeredOwner = void 0, sourceUrls = [], taxNumber = void 0, vatValid = void 0, aiScore = void 0, nameMatch = void 0, officialName = void 0, officialAddress = void 0) {
2435
2449
  this.status = status;
2436
2450
  this.vatNumber = vatNumber;
2437
2451
  this.vatType = vatType;
@@ -2444,6 +2458,15 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2444
2458
  this.providerVerdicts = providerVerdicts;
2445
2459
  this.addressQuality = addressQuality;
2446
2460
  this.rejectedCandidates = rejectedCandidates;
2461
+ this.sourceUrl = sourceUrl;
2462
+ this.registeredOwner = registeredOwner;
2463
+ this.sourceUrls = sourceUrls;
2464
+ this.taxNumber = taxNumber;
2465
+ this.vatValid = vatValid;
2466
+ this.aiScore = aiScore;
2467
+ this.nameMatch = nameMatch;
2468
+ this.officialName = officialName;
2469
+ this.officialAddress = officialAddress;
2447
2470
  }
2448
2471
  status;
2449
2472
  vatNumber;
@@ -2457,6 +2480,19 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2457
2480
  providerVerdicts;
2458
2481
  addressQuality;
2459
2482
  rejectedCandidates;
2483
+ sourceUrl;
2484
+ registeredOwner;
2485
+ sourceUrls;
2486
+ taxNumber;
2487
+ vatValid;
2488
+ aiScore;
2489
+ nameMatch;
2490
+ officialName;
2491
+ officialAddress;
2492
+ /** True when the register knows the number under a different name than the one requested. */
2493
+ nameMismatch() {
2494
+ return this.nameMatch === "mismatch";
2495
+ }
2460
2496
  /** True when a VAT number was found but rejected by the official check. */
2461
2497
  hasRejectedCandidates() {
2462
2498
  return this.rejectedCandidates.length > 0;
@@ -2466,6 +2502,13 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2466
2502
  const v = data[key];
2467
2503
  return typeof v === "string" ? v : void 0;
2468
2504
  };
2505
+ const text = (key) => {
2506
+ const v = str(key)?.trim();
2507
+ return v ? v : void 0;
2508
+ };
2509
+ const isWebUrl = (value) => typeof value === "string" && /^https?:\/\/\S+$/i.test(value.trim());
2510
+ const url = text("sourceUrl");
2511
+ const urls = data["sourceUrls"];
2469
2512
  const num = (key) => {
2470
2513
  const v = data[key];
2471
2514
  return typeof v === "number" ? v : void 0;
@@ -2484,7 +2527,16 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2484
2527
  toSmartEnrichmentMode(data["mode"]),
2485
2528
  Array.isArray(verdicts) ? verdicts.filter((v) => typeof v === "object" && v !== null) : [],
2486
2529
  typeof quality === "object" && quality !== null ? quality : void 0,
2487
- toRejectedCandidates(data["rejectedCandidates"])
2530
+ toRejectedCandidates(data["rejectedCandidates"]),
2531
+ url && isWebUrl(url) ? url : void 0,
2532
+ text("registeredOwner"),
2533
+ Array.isArray(urls) ? [...new Set(urls.filter(isWebUrl).map((u) => u.trim()))] : [],
2534
+ text("taxNumber"),
2535
+ typeof data["vatValid"] === "boolean" ? data["vatValid"] : void 0,
2536
+ num("aiScore"),
2537
+ data["nameMatch"] === "ok" || data["nameMatch"] === "mismatch" ? data["nameMatch"] : void 0,
2538
+ text("officialName"),
2539
+ toOfficialAddress(data["officialAddress"])
2488
2540
  );
2489
2541
  }
2490
2542
  toArray() {
@@ -2500,7 +2552,16 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
2500
2552
  mode: this.mode ?? null,
2501
2553
  providerVerdicts: this.providerVerdicts,
2502
2554
  addressQuality: this.addressQuality ?? null,
2503
- rejectedCandidates: this.rejectedCandidates.map((c) => ({ vatNumber: c.vatNumber, reason: c.reason }))
2555
+ rejectedCandidates: this.rejectedCandidates.map((c) => ({ vatNumber: c.vatNumber, reason: c.reason })),
2556
+ sourceUrl: this.sourceUrl ?? null,
2557
+ registeredOwner: this.registeredOwner ?? null,
2558
+ sourceUrls: this.sourceUrls,
2559
+ taxNumber: this.taxNumber ?? null,
2560
+ vatValid: this.vatValid ?? null,
2561
+ aiScore: this.aiScore ?? null,
2562
+ nameMatch: this.nameMatch ?? null,
2563
+ officialName: this.officialName ?? null,
2564
+ officialAddress: this.officialAddress ?? null
2504
2565
  };
2505
2566
  }
2506
2567
  };
@@ -3778,7 +3839,7 @@ var AuthRetryHttpClient = class {
3778
3839
  };
3779
3840
 
3780
3841
  // src/version.ts
3781
- var SDK_VERSION = "1.4.0";
3842
+ var SDK_VERSION = "1.6.0";
3782
3843
 
3783
3844
  // src/http/SdkVersionHttpClient.ts
3784
3845
  var SDK_VERSION_HEADER = "X-Taxora-SDK-Version";