@taxora/sdk 1.7.0 → 1.8.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 +23 -0
- package/README.md +20 -0
- package/dist/index.cjs +124 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -3
- package/dist/index.d.ts +87 -3
- package/dist/index.js +122 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@taxora/sdk` are documented here. Versions follow [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [1.8.0] — 2026-10-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`smartEnrichment.recheck(jobId, { rows?, dryRun? })`** searches again for rows without a usable answer
|
|
10
|
+
(`not_found`, or a number registered to another company). Every recheck counts as a check like a new lookup (Deep
|
|
11
|
+
Verify ×2), found or not; max 3 per row, 7 days apart; `no_vat_exists` and found rows are never rechecked.
|
|
12
|
+
`dryRun` reports rows, skipped rows and cost without starting anything. Returns `SmartEnrichmentRecheck`
|
|
13
|
+
(`rows`, `checks`, `skipped`, `dryRun`).
|
|
14
|
+
- **`SmartEnrichmentJob.recheck`** (`SmartEnrichmentRecheckState`: `eligible`, `runs`, `maxPerRow`, `cooldownDays`,
|
|
15
|
+
`isActive()`) and **`recheckCount` / `lastRecheckedAt`** on each result.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Bundled OpenAPI specs (`resources/`) refreshed from the current API.
|
|
20
|
+
|
|
21
|
+
## [1.7.1] — 2026-10-24
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **`smartEnrichment.export()` keeps the CSV's UTF-8 BOM.** `Response.text()` silently dropped it, so Excel opened a
|
|
26
|
+
saved export as ANSI and garbled umlauts. The body is now returned byte-for-byte, as documented.
|
|
27
|
+
|
|
5
28
|
## [1.7.0] — 2026-10-24
|
|
6
29
|
|
|
7
30
|
### Added
|
package/README.md
CHANGED
|
@@ -448,6 +448,26 @@ for (const row of history) {
|
|
|
448
448
|
}
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
+
### Check rows again
|
|
452
|
+
|
|
453
|
+
Search once more for rows without a usable answer (`not_found`, or a number registered to another company). Every
|
|
454
|
+
recheck counts as a check like a new lookup (Deep Verify ×2), whether a VAT number is found or not. A row can be
|
|
455
|
+
rechecked up to 3 times, 7 days apart; `no_vat_exists` and found rows are never rechecked.
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
// What would run, and what it costs — nothing is started
|
|
459
|
+
const plan = await client.smartEnrichment.recheck(jobId, { dryRun: true });
|
|
460
|
+
console.log(plan.rows.length, 'rows,', plan.checks, 'checks, skipped:', plan.skipped);
|
|
461
|
+
|
|
462
|
+
await client.smartEnrichment.recheck(jobId); // every row that qualifies
|
|
463
|
+
await client.smartEnrichment.recheck(jobId, { rows: [3, 7] }); // or just these rows
|
|
464
|
+
|
|
465
|
+
// Improved rows arrive via the `enrichment.updated` webhook; or poll:
|
|
466
|
+
const job = await client.smartEnrichment.get(jobId);
|
|
467
|
+
console.log(job.recheck?.isActive() ? 'still rechecking' : 'done');
|
|
468
|
+
console.log(job.results[3]?.recheckCount, job.results[3]?.lastRecheckedAt);
|
|
469
|
+
```
|
|
470
|
+
|
|
451
471
|
### Quota usage & billing history
|
|
452
472
|
|
|
453
473
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,8 @@ __export(index_exports, {
|
|
|
63
63
|
SmartEnrichmentHistoryRow: () => SmartEnrichmentHistoryRow,
|
|
64
64
|
SmartEnrichmentJob: () => SmartEnrichmentJob,
|
|
65
65
|
SmartEnrichmentMode: () => SmartEnrichmentMode,
|
|
66
|
+
SmartEnrichmentRecheck: () => SmartEnrichmentRecheck,
|
|
67
|
+
SmartEnrichmentRecheckState: () => SmartEnrichmentRecheckState,
|
|
66
68
|
SmartEnrichmentRejectionReason: () => SmartEnrichmentRejectionReason,
|
|
67
69
|
SmartEnrichmentResource: () => SmartEnrichmentResource,
|
|
68
70
|
SmartEnrichmentStatistics: () => SmartEnrichmentStatistics,
|
|
@@ -2318,6 +2320,73 @@ var EReportingEndpoint = class {
|
|
|
2318
2320
|
}
|
|
2319
2321
|
};
|
|
2320
2322
|
|
|
2323
|
+
// src/dto/SmartEnrichmentRecheck.ts
|
|
2324
|
+
var toIndexes = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "number" && Number.isInteger(v)) : [];
|
|
2325
|
+
var SmartEnrichmentRecheck = class _SmartEnrichmentRecheck {
|
|
2326
|
+
constructor(jobId, rows, checks, skipped, dryRun) {
|
|
2327
|
+
this.jobId = jobId;
|
|
2328
|
+
this.rows = rows;
|
|
2329
|
+
this.checks = checks;
|
|
2330
|
+
this.skipped = skipped;
|
|
2331
|
+
this.dryRun = dryRun;
|
|
2332
|
+
}
|
|
2333
|
+
jobId;
|
|
2334
|
+
rows;
|
|
2335
|
+
checks;
|
|
2336
|
+
skipped;
|
|
2337
|
+
dryRun;
|
|
2338
|
+
static fromArray(data) {
|
|
2339
|
+
const skipped = {};
|
|
2340
|
+
const rawSkipped = data["skipped"];
|
|
2341
|
+
if (typeof rawSkipped === "object" && rawSkipped !== null && !Array.isArray(rawSkipped)) {
|
|
2342
|
+
for (const [reason, count] of Object.entries(rawSkipped)) {
|
|
2343
|
+
if (typeof count === "number") skipped[reason] = count;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
return new _SmartEnrichmentRecheck(
|
|
2347
|
+
typeof data["jobId"] === "string" ? data["jobId"] : "",
|
|
2348
|
+
toIndexes(data["rows"]),
|
|
2349
|
+
typeof data["checks"] === "number" ? data["checks"] : 0,
|
|
2350
|
+
skipped,
|
|
2351
|
+
data["dryRun"] === true
|
|
2352
|
+
);
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
var SmartEnrichmentRecheckState = class _SmartEnrichmentRecheckState {
|
|
2356
|
+
constructor(eligible, runs, maxPerRow, cooldownDays) {
|
|
2357
|
+
this.eligible = eligible;
|
|
2358
|
+
this.runs = runs;
|
|
2359
|
+
this.maxPerRow = maxPerRow;
|
|
2360
|
+
this.cooldownDays = cooldownDays;
|
|
2361
|
+
}
|
|
2362
|
+
eligible;
|
|
2363
|
+
runs;
|
|
2364
|
+
maxPerRow;
|
|
2365
|
+
cooldownDays;
|
|
2366
|
+
static fromArray(data) {
|
|
2367
|
+
const runs = {};
|
|
2368
|
+
const rawRuns = data["runs"];
|
|
2369
|
+
if (typeof rawRuns === "object" && rawRuns !== null && !Array.isArray(rawRuns)) {
|
|
2370
|
+
for (const [index, run] of Object.entries(rawRuns)) {
|
|
2371
|
+
if (!/^\d+$/.test(index) || typeof run !== "object" || run === null) continue;
|
|
2372
|
+
const { state, resolved } = run;
|
|
2373
|
+
if (state !== "queued" && state !== "running" && state !== "finished" && state !== "failed") continue;
|
|
2374
|
+
runs[Number(index)] = typeof resolved === "boolean" ? { state, resolved } : { state };
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return new _SmartEnrichmentRecheckState(
|
|
2378
|
+
toIndexes(data["eligible"]),
|
|
2379
|
+
runs,
|
|
2380
|
+
typeof data["maxPerRow"] === "number" ? data["maxPerRow"] : 3,
|
|
2381
|
+
typeof data["cooldownDays"] === "number" ? data["cooldownDays"] : 7
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2384
|
+
/** True while any recheck of this lookup is queued or running. */
|
|
2385
|
+
isActive() {
|
|
2386
|
+
return Object.values(this.runs).some((run) => run.state === "queued" || run.state === "running");
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
|
|
2321
2390
|
// src/enums/SmartEnrichmentMode.ts
|
|
2322
2391
|
var SmartEnrichmentMode = {
|
|
2323
2392
|
DEFAULT: "default",
|
|
@@ -2447,7 +2516,7 @@ function toOfficialAddress(value) {
|
|
|
2447
2516
|
return Object.keys(address).length > 0 ? address : void 0;
|
|
2448
2517
|
}
|
|
2449
2518
|
var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
2450
|
-
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, taxNumberType = void 0, taxNumberLabel = void 0, taxNumberSource = void 0) {
|
|
2519
|
+
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, taxNumberType = void 0, taxNumberLabel = void 0, taxNumberSource = void 0, recheckCount = void 0, lastRecheckedAt = void 0) {
|
|
2451
2520
|
this.status = status;
|
|
2452
2521
|
this.vatNumber = vatNumber;
|
|
2453
2522
|
this.vatType = vatType;
|
|
@@ -2472,6 +2541,8 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2472
2541
|
this.taxNumberType = taxNumberType;
|
|
2473
2542
|
this.taxNumberLabel = taxNumberLabel;
|
|
2474
2543
|
this.taxNumberSource = taxNumberSource;
|
|
2544
|
+
this.recheckCount = recheckCount;
|
|
2545
|
+
this.lastRecheckedAt = lastRecheckedAt;
|
|
2475
2546
|
}
|
|
2476
2547
|
status;
|
|
2477
2548
|
vatNumber;
|
|
@@ -2497,6 +2568,8 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2497
2568
|
taxNumberType;
|
|
2498
2569
|
taxNumberLabel;
|
|
2499
2570
|
taxNumberSource;
|
|
2571
|
+
recheckCount;
|
|
2572
|
+
lastRecheckedAt;
|
|
2500
2573
|
/** True when the register knows the number under a different name than the one requested. */
|
|
2501
2574
|
nameMismatch() {
|
|
2502
2575
|
return this.nameMatch === "mismatch";
|
|
@@ -2547,7 +2620,9 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2547
2620
|
toOfficialAddress(data["officialAddress"]),
|
|
2548
2621
|
text("taxNumberType"),
|
|
2549
2622
|
text("taxNumberLabel"),
|
|
2550
|
-
data["taxNumberSource"] === "vat_id" || data["taxNumberSource"] === "company_website" ? data["taxNumberSource"] : void 0
|
|
2623
|
+
data["taxNumberSource"] === "vat_id" || data["taxNumberSource"] === "company_website" ? data["taxNumberSource"] : void 0,
|
|
2624
|
+
num("recheckCount"),
|
|
2625
|
+
text("lastRecheckedAt")
|
|
2551
2626
|
);
|
|
2552
2627
|
}
|
|
2553
2628
|
toArray() {
|
|
@@ -2575,20 +2650,23 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2575
2650
|
officialAddress: this.officialAddress ?? null,
|
|
2576
2651
|
taxNumberType: this.taxNumberType ?? null,
|
|
2577
2652
|
taxNumberLabel: this.taxNumberLabel ?? null,
|
|
2578
|
-
taxNumberSource: this.taxNumberSource ?? null
|
|
2653
|
+
taxNumberSource: this.taxNumberSource ?? null,
|
|
2654
|
+
recheckCount: this.recheckCount ?? null,
|
|
2655
|
+
lastRecheckedAt: this.lastRecheckedAt ?? null
|
|
2579
2656
|
};
|
|
2580
2657
|
}
|
|
2581
2658
|
};
|
|
2582
2659
|
|
|
2583
2660
|
// src/dto/SmartEnrichmentJob.ts
|
|
2584
2661
|
var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
2585
|
-
constructor(jobId, status, itemCount, completedCount, foundCount, results) {
|
|
2662
|
+
constructor(jobId, status, itemCount, completedCount, foundCount, results, recheck = void 0) {
|
|
2586
2663
|
this.jobId = jobId;
|
|
2587
2664
|
this.status = status;
|
|
2588
2665
|
this.itemCount = itemCount;
|
|
2589
2666
|
this.completedCount = completedCount;
|
|
2590
2667
|
this.foundCount = foundCount;
|
|
2591
2668
|
this.results = results;
|
|
2669
|
+
this.recheck = recheck;
|
|
2592
2670
|
}
|
|
2593
2671
|
jobId;
|
|
2594
2672
|
status;
|
|
@@ -2596,6 +2674,7 @@ var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
|
2596
2674
|
completedCount;
|
|
2597
2675
|
foundCount;
|
|
2598
2676
|
results;
|
|
2677
|
+
recheck;
|
|
2599
2678
|
static fromArray(data) {
|
|
2600
2679
|
const num = (key) => {
|
|
2601
2680
|
const v = data[key];
|
|
@@ -2613,7 +2692,8 @@ var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
|
2613
2692
|
num("itemCount"),
|
|
2614
2693
|
num("completedCount"),
|
|
2615
2694
|
num("foundCount"),
|
|
2616
|
-
results
|
|
2695
|
+
results,
|
|
2696
|
+
typeof data["recheck"] === "object" && data["recheck"] !== null && !Array.isArray(data["recheck"]) ? SmartEnrichmentRecheckState.fromArray(data["recheck"]) : void 0
|
|
2617
2697
|
);
|
|
2618
2698
|
}
|
|
2619
2699
|
isProcessing() {
|
|
@@ -2859,6 +2939,41 @@ var SmartEnrichmentEndpoint = class {
|
|
|
2859
2939
|
const data = await this.parseJsonResponse(response);
|
|
2860
2940
|
return SmartEnrichmentJob.fromArray(data);
|
|
2861
2941
|
}
|
|
2942
|
+
/**
|
|
2943
|
+
* Search again for rows of a finished lookup that have no usable answer (`not_found`, or a
|
|
2944
|
+
* number registered to another company). Without `rows` every row that qualifies is rechecked.
|
|
2945
|
+
*
|
|
2946
|
+
* Every recheck counts as a check like a new lookup (Deep Verify ×2), whether a VAT number is
|
|
2947
|
+
* found or not. A row can be rechecked up to 3 times, with 7 days between two rechecks;
|
|
2948
|
+
* `no_vat_exists` and found rows are never rechecked. Pass `dryRun` to see which rows would run
|
|
2949
|
+
* and what they cost without starting anything. Improved rows arrive via the
|
|
2950
|
+
* `enrichment.updated` webhook; `get(jobId).recheck` shows the progress.
|
|
2951
|
+
*
|
|
2952
|
+
* Throws a ValidationException when nothing can be rechecked, the lookup is still running, or
|
|
2953
|
+
* rechecks are not available (sandbox, flat-fee import), and an HttpException (429) when the
|
|
2954
|
+
* start credit or monthly hard cap does not cover it.
|
|
2955
|
+
*/
|
|
2956
|
+
async recheck(jobId, options = {}) {
|
|
2957
|
+
this.validateJobId(jobId);
|
|
2958
|
+
const body = {};
|
|
2959
|
+
if (options.rows !== void 0) {
|
|
2960
|
+
if (options.rows.length === 0) {
|
|
2961
|
+
throw new TaxoraException("rows must not be empty; omit it to recheck every row that qualifies.");
|
|
2962
|
+
}
|
|
2963
|
+
if (options.rows.some((index) => !Number.isInteger(index) || index < 0)) {
|
|
2964
|
+
throw new TaxoraException("rows must contain 0-based row indexes (integers >= 0).");
|
|
2965
|
+
}
|
|
2966
|
+
body["rows"] = [...new Set(options.rows)];
|
|
2967
|
+
}
|
|
2968
|
+
if (options.dryRun) body["dryRun"] = true;
|
|
2969
|
+
const response = await this.sendRequest(
|
|
2970
|
+
"POST",
|
|
2971
|
+
`${this.baseUrl}/smart-enrichment/${encodeURIComponent(jobId)}/recheck`,
|
|
2972
|
+
body
|
|
2973
|
+
);
|
|
2974
|
+
const data = await this.parseJsonResponse(response, [200, 202]);
|
|
2975
|
+
return SmartEnrichmentRecheck.fromArray(data);
|
|
2976
|
+
}
|
|
2862
2977
|
/**
|
|
2863
2978
|
* Poll get(jobId) until the job is no longer processing (completed, failed or resolved).
|
|
2864
2979
|
* Throws a TaxoraException when the job does not finish within `timeoutMs`.
|
|
@@ -3063,7 +3178,7 @@ var SmartEnrichmentEndpoint = class {
|
|
|
3063
3178
|
* verbatim (text/csv) instead of parsing JSON.
|
|
3064
3179
|
*/
|
|
3065
3180
|
async parseCsvResponse(response) {
|
|
3066
|
-
const responseText = await response.
|
|
3181
|
+
const responseText = new TextDecoder("utf-8", { ignoreBOM: true }).decode(await response.arrayBuffer());
|
|
3067
3182
|
if (response.status === 422) {
|
|
3068
3183
|
throw new ValidationException(
|
|
3069
3184
|
jsonErrorMessage(responseText) ?? "Validation failed",
|
|
@@ -4033,7 +4148,7 @@ var AuthRetryHttpClient = class {
|
|
|
4033
4148
|
};
|
|
4034
4149
|
|
|
4035
4150
|
// src/version.ts
|
|
4036
|
-
var SDK_VERSION = "1.
|
|
4151
|
+
var SDK_VERSION = "1.8.0";
|
|
4037
4152
|
|
|
4038
4153
|
// src/http/SdkVersionHttpClient.ts
|
|
4039
4154
|
var SDK_VERSION_HEADER = "X-Taxora-SDK-Version";
|
|
@@ -4264,6 +4379,8 @@ function toBytes(rawBody) {
|
|
|
4264
4379
|
SmartEnrichmentHistoryRow,
|
|
4265
4380
|
SmartEnrichmentJob,
|
|
4266
4381
|
SmartEnrichmentMode,
|
|
4382
|
+
SmartEnrichmentRecheck,
|
|
4383
|
+
SmartEnrichmentRecheckState,
|
|
4267
4384
|
SmartEnrichmentRejectionReason,
|
|
4268
4385
|
SmartEnrichmentResource,
|
|
4269
4386
|
SmartEnrichmentStatistics,
|