evatr-api 0.1.1

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RL Recht logisch GmbH & Co. KG open-source@rechtlogisch.de
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,434 @@
1
+ ![Recht logisch eVatR banner image](rechtlogisch-evatr-api-banner.png)
2
+
3
+ [![Tests](https://img.shields.io/github/actions/workflow/status/rechtlogisch/evatr-js/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/rechtlogisch/evatr-js/actions/workflows/run-tests.yml)
4
+ [![codecov](https://codecov.io/github/rechtlogisch/evatr-js/graph/badge.svg?token=BJ9JT1CR2S)](https://codecov.io/github/rechtlogisch/evatr-js)
5
+ [![NPM Version](https://img.shields.io/npm/v/evatr-api)](https://www.npmjs.com/package/evatr-api)
6
+
7
+ # evatr-api
8
+
9
+ > Checks a VAT-ID using the eVatR REST-API of the German Federal Central Tax Office (Bundeszentralamt für Steuern, BZSt)
10
+
11
+ > [!CAUTION]
12
+ > This package is in early development and is not yet ready for production use. It is currently being tested and may undergo significant changes.
13
+
14
+ > [!IMPORTANT]
15
+ > This is an unofficial wrapper for the eVatR API. For official documentation and terms of use, please refer to the [German Federal Central Tax Office (BZSt)](https://www.bzst.de/DE/Unternehmen/Identifikationsnummern/Umsatzsteuer-Identifikationsnummer/umsatzsteuer-identifikationsnummer_node.html) website.
16
+
17
+ > [!NOTE]
18
+ > This package uses the new REST-API released in July 2025. The old XML-RPC API is being discontinued and will be sunset on **November 30th, 2025** (based on information from BZSt-Newsletter USTKV 01/2025 dated July 1st, 2025).
19
+
20
+ ## Installation
21
+
22
+ You can install the package via npm:
23
+
24
+ ```bash
25
+ npm install evatr-api
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { EvatrClient } from 'evatr-api';
32
+
33
+ const client = new EvatrClient();
34
+
35
+ // Simple validation (only checks if VAT-ID is valid)
36
+ const result = await client.validateSimple({
37
+ vatIdOwn: 'DE123456789',
38
+ vatIdForeign: 'ATU12345678'
39
+ });
40
+
41
+ console.log(result);
42
+ ```
43
+
44
+ or
45
+
46
+ ```typescript
47
+ // Qualified validation with company data
48
+ const result = await client.validateQualified({
49
+ vatIdOwn: 'DE123456789',
50
+ vatIdForeign: 'ATU12345678',
51
+ company: 'Test GmbH',
52
+ location: 'Wien'
53
+ });
54
+
55
+ console.log(result);
56
+ ```
57
+
58
+ > [!TIP]
59
+ > You might want to take a look at some [examples](./examples/).
60
+
61
+ ## Status Codes
62
+
63
+ The API returns various status codes. You can check the status using the client methods:
64
+
65
+ ```typescript
66
+ const result = await client.validateSimple({ /* ... */ });
67
+
68
+ client.isSuccessStatus(result.status); // true for valid VAT-IDs
69
+ client.isErrorStatus(result.status); // true for errors
70
+ client.isWarningStatus(result.status); // true for warnings
71
+
72
+ // Get human-readable message
73
+ const message = client.getStatusMessage(result.status);
74
+ console.log(message?.message); // Message in German
75
+ ```
76
+
77
+ ## API Reference
78
+
79
+ ### Constructor
80
+
81
+ ```typescript
82
+ const client = new EvatrClient(config?: EvatrClientConfig);
83
+ ```
84
+
85
+ **Configuration Options:**
86
+ - `timeout?: number` - Request timeout in milliseconds (default: 30000 ms; = 30 s)
87
+ - `headers?: Record<string, string>` - Custom headers to include with requests
88
+
89
+ ### Methods
90
+
91
+ #### Simple Validation
92
+
93
+ Validates only the VAT-ID without company data verification:
94
+
95
+ ```typescript
96
+ await client.validateSimple({
97
+ vatIdOwn: 'DE123456789', // Your German VAT-ID (required)
98
+ vatIdForeign: 'ATU12345678', // VAT-ID to validate (required)
99
+ includeRaw: true, // Include raw response (optional)
100
+ });
101
+ ```
102
+
103
+ #### Qualified Validation
104
+
105
+ Validates VAT-ID and verifies company data:
106
+
107
+ ```typescript
108
+ await client.validateQualified({
109
+ vatIdOwn: 'DE123456789', // Your German VAT-ID (required)
110
+ vatIdForeign: 'ATU12345678', // VAT-ID to validate (required)
111
+ company: 'Test GmbH', // Company name (required)
112
+ location: 'Wien', // City (required)
113
+ street: 'Musterstr. 1', // Street address (optional)
114
+ zip: '1010', // Postal code (optional)
115
+ includeRaw: true, // Include raw response (optional)
116
+ });
117
+ ```
118
+
119
+ > [!TIP]
120
+ > You may set `true` as the second parameter to get an [`ExtendedResponse`](#extended-response) object.
121
+
122
+ #### Utility Methods
123
+
124
+ ```typescript
125
+ // Get status messages
126
+ const statusMessages = await client.getStatusMessages();
127
+
128
+ // Get EU member states and their availability
129
+ const memberStates = await client.getEUMemberStates();
130
+
131
+ // Get content of specific status message
132
+ const message = client.getStatusMessage('evatr-0000');
133
+
134
+ // Check status types
135
+ client.isSuccessStatus('evatr-0000'); // true
136
+ client.isErrorStatus('evatr-0004'); // true
137
+ client.isWarningStatus('evatr-2002'); // true
138
+ ```
139
+
140
+ ### Request
141
+
142
+ The API uses German terms, which have been mapped to the following English parameters:
143
+
144
+ | BZSt API | evatr-api |
145
+ |-------------------|----------------|
146
+ | anfragendeUstid | vatIdOwn |
147
+ | angefragteUstid | vatIdForeign |
148
+ | firmenname | company |
149
+ | ort | location |
150
+ | strasse | street |
151
+ | plz | zip |
152
+
153
+ ### Response
154
+
155
+ All validation methods return a `Response` object by default:
156
+
157
+ ```typescript
158
+ interface Response {
159
+ timestamp: string; // Query timestamp (ISO string)
160
+ status: string; // Status code (e.g., "evatr-0000")
161
+ vatIdOwn: string; // Normalized own VAT-ID used for API request
162
+ vatIdForeign: string; // Normalized foreign VAT-ID used for API request
163
+ validFrom?: string; // Valid from date (ISO string)
164
+ validTill?: string; // Valid until date (ISO string)
165
+ company?: QualifiedResultCode; // Company name validation result
166
+ street?: QualifiedResultCode; // Street validation result
167
+ zip?: QualifiedResultCode; // ZIP code validation result
168
+ location?: QualifiedResultCode; // Location validation result
169
+ raw?: string; // Raw response from API (only if includeRaw is true)
170
+ }
171
+ ```
172
+
173
+ The API uses German terms, which have been mapped to the following English parameters:
174
+
175
+ | BZSt API | evatr-api |
176
+ |-----------------|---------------|
177
+ | anfrageZeitpunkt| timestamp |
178
+ | status | status |
179
+ | gueltigAb | validFrom |
180
+ | gueltigBis | validTill |
181
+ | ergFirmenname | company |
182
+ | ergStrasse | street |
183
+ | ergPlz | zip |
184
+ | ergOrt | location |
185
+
186
+ #### Extended Response
187
+
188
+ By passing `true` as the second parameter to function `validateSimple({...}, true)` or `validateQualified({...}, true)` an `ExtendedResponse` object is being returned, which maps date string to date objects and returns `valid` and `message` keys:
189
+
190
+ ```typescript
191
+ interface ExtendedResponse {
192
+ timestamp: Date; // Date object
193
+ valid: boolean; // true if isSuccessStatus()
194
+ status: string;
195
+ message?: string; // German description for the status
196
+ vatIdOwn: string; // Normalized own VAT-ID used for API request
197
+ vatIdForeign: string; // Normalized foreign VAT-ID used for API request
198
+ validFrom?: Date; // Date object
199
+ validTill?: Date; // Date object
200
+ company?: QualifiedResultCode;
201
+ street?: QualifiedResultCode;
202
+ zip?: QualifiedResultCode;
203
+ location?: QualifiedResultCode;
204
+ raw?: string;
205
+ }
206
+ ```
207
+
208
+ ### Validation Results (Qualified Validation)
209
+
210
+ For qualified validation, the response includes validation results for each field:
211
+
212
+ - **A** - Data matches registered information
213
+ - **B** - Data does not match registered information
214
+ - **C** - Data was not requested
215
+ - **D** - Data not provided by the EU member state
216
+
217
+ ## Utility Functions
218
+
219
+ The library includes helpful utility functions via `EvatrUtils`:
220
+
221
+ ```typescript
222
+ import { EvatrUtils } from 'evatr-api';
223
+
224
+ // Validate VAT-ID format
225
+ EvatrUtils.checkVatIdSyntaxForCountry('DE123456789', 'DE'); // true
226
+
227
+ // Get country information
228
+ EvatrUtils.getCountryName('DE'); // 'Germany'
229
+ EvatrUtils.isEUMemberState('DE'); // true
230
+
231
+ // Check validation capability
232
+ EvatrUtils.canValidate('DE123456789', 'ATU12345678'); // true
233
+ EvatrUtils.canValidate('DE123456789', 'DE987654321'); // false (can't validate DE->DE)
234
+
235
+ // Get test VAT-IDs for development
236
+ const testIds = EvatrUtils.getTestVatIds();
237
+ ```
238
+
239
+ ## Migration Helper (Backward Compatibility)
240
+
241
+ For users migrating from the [evatr](https://github.com/qqilihq/evatr) library, we provide a migration helper that maintains API compatibility.
242
+
243
+ > [!IMPORTANT]
244
+ > The migration helper was introduced because the German Federal Central Tax Office is **sunsetting the XML-RPC API on November 30th, 2025**. This helper allows existing code to work with minimal changes while using the new REST API under the hood.
245
+
246
+ ### Why the Migration Helper?
247
+
248
+ The new REST API has several differences from the XML-RPC API:
249
+ - JSON responses instead of XML
250
+ - Different parameter names
251
+ - Different response structure
252
+ - Different error codes and messages
253
+ - There is no standard yet on English naming conventions for request and response parameters in context of VAT-ID validation
254
+
255
+ ### Usage
256
+
257
+ ```typescript
258
+ import { EvatrMigrationHelper as evatr } from 'evatr-api';
259
+
260
+ // Simple validation (matches original evatr API)
261
+ const result = await evatr.checkSimple({
262
+ ownVatNumber: 'DE123456789',
263
+ validateVatNumber: 'ATU12345678'
264
+ });
265
+
266
+ // Qualified validation (matches original evatr API)
267
+ const qualifiedResult = await evatr.checkQualified({
268
+ ownVatNumber: 'DE123456789',
269
+ validateVatNumber: 'ATU12345678',
270
+ companyName: 'Musterhaus GmbH & Co KG',
271
+ street: 'Musterstrasse 22'
272
+ zip: '12345',
273
+ city: 'musterort',
274
+ });
275
+ ```
276
+
277
+ ### Breaking Changes
278
+
279
+ While the migration helper tries to maintain API compatibility, there are some unavoidable breaking changes:
280
+
281
+ | Change | evatr | evatr-api) |
282
+ |--------|---------------|----------------------------------|
283
+ | Raw data parameter | `includeRawXml` | `includeRaw` |
284
+ | Raw data response | `rawXml` (XML string) | `raw` (JSON string) |
285
+ | Error codes | XML-RPC specific codes | Mapped to legacy codes (best effort) |
286
+ | Error descriptions | Based on error code | Based on REST API status messages |
287
+ | Additional field | - | `status` (new REST API status code) |
288
+
289
+ > [!NOTE]
290
+ > API status codes have been [mapped](./src/migration-helper.ts#L33) to legacy codes to the best of our knowledge. If an API status does not correspond to a legacy code, the 999 legacy code is being returned. We recommend to relay on API status.
291
+
292
+ > [!TIP]
293
+ > See the [migration helper example](./examples/migration-helper.ts) for a complete usage demonstration.
294
+
295
+ ### Mapping
296
+
297
+ The following tables show the parameter naming mapping between [evatr](https://github.com/qqilihq/evatr) and [evatr-api](https://github.com/rechtlogisch/evatr-js):
298
+
299
+ #### Request
300
+
301
+ | evatr | evatr-api |
302
+ |-------------------------|------------------------------|
303
+ | `ownVatNumber` | `vatIdOwn` |
304
+ | `validateVatNumber` | `vatIdForeign` |
305
+ | `companyName` | `company` |
306
+ | `city` | `location` |
307
+ | `street` | `street` |
308
+ | `zip` | `zip` |
309
+ | `includeRaw` | `includeRaw` |
310
+
311
+ #### Response
312
+
313
+ | evatr | evatr-api |
314
+ |--------------------------------|-----------------------------------------|
315
+ | `raw` (XML) | `raw` (JSON) |
316
+ | `date` | `timestamp` {0, 10} (format YYYY-MM-DD) |
317
+ | `time` | `timestamp` {11, 8} (format HH:MM:SS) |
318
+ | `errorCode` | - (replaced by `status`) |
319
+ | `errorDescription` | - (use getStatusMessage() or `message` in ExtendedResponse) |
320
+ | - (exists in migration helper) | `status` |
321
+ | `ownVatNumber` | `vatIdOwn` |
322
+ | `validatedVatNumber` | `vatIdForeign` |
323
+ | `validFrom` | `validFrom` |
324
+ | `validTill` | `validTill` |
325
+ | `valid` | `valid` |
326
+ | `resultName` | `company` |
327
+ | `resultCity` | `location` |
328
+ | `resultStreet` | `street` |
329
+ | `resultZip` | `zip` |
330
+ | `resultNameDescription` | - (use explainQualifiedResultCode()) |
331
+ | `resultCityDescription` | - (use explainQualifiedResultCode()) |
332
+ | `resultStreetDescription` | - (use explainQualifiedResultCode()) |
333
+ | `resultZipDescription` | - (use explainQualifiedResultCode()) |
334
+
335
+
336
+ ## Error Handling
337
+
338
+ The library throws `EvatrApiError` for API-related errors:
339
+
340
+ ```typescript
341
+ try {
342
+ const result = await client.validateSimple({
343
+ anfragendeUstid: 'DE123456789',
344
+ angefragteUstid: 'INVALID'
345
+ });
346
+ } catch (error) {
347
+ if (error.name === 'EvatrApiError') {
348
+ console.log('Status:', error.status);
349
+ console.log('HTTP Code:', error.http);
350
+ console.log('Field:', error.field);
351
+ console.log('Message:', error.message);
352
+ }
353
+ }
354
+ ```
355
+
356
+ ## API Updates
357
+
358
+ The library includes utilities to check for API updates:
359
+
360
+ ```bash
361
+ # Check for all updates
362
+ npm run update-api check
363
+
364
+ # Check only API documentation
365
+ npm run update-api api-docs
366
+
367
+ # Check only status messages
368
+ npm run update-api status-messages
369
+ ```
370
+
371
+ ### Update Workflow
372
+
373
+ 1. **Check for updates**: Run `npm run update-api check` to see if there are new versions
374
+ 2. **Inspect output**: Status message changes are displayed with added, removed, and modified messages
375
+ 3. **Compare differences**: Compare current file with updated versions using for example `diff`, New files are saved with timestamps (e.g., `statusmeldungen-2025-08-03.json`)
376
+ 4. **Update constants**: Update the TypeScript constants file with new messages:
377
+
378
+ ```bash
379
+ npm run update-api update-constants ./docs/statusmeldungen-2025-08-03.json
380
+ ```
381
+
382
+ ## Rate Limits and Best Practices
383
+
384
+ - The BZSt API has rate limits for qualified validation requests
385
+ - Add delays between requests when validating multiple VAT-IDs
386
+ - Cache results when possible to avoid unnecessary API calls (for example for 12 hours)
387
+ - Handle errors gracefully and provide meaningful feedback to users
388
+
389
+ ## Testing
390
+
391
+ ```bash
392
+ npm test
393
+ ```
394
+
395
+ ### Dummy data
396
+
397
+ The library includes test VAT-IDs and information that can be used for testing. These are official test VAT-IDs provided by the API documentation:
398
+
399
+ ```typescript
400
+ const testRequest = {
401
+ anfragendeUstid: 'DE123456789',
402
+ angefragteUstid: 'ATU12345678'
403
+ };
404
+
405
+ const qualifiedTestRequest = {
406
+ anfragendeUstid: 'DE123456789',
407
+ angefragteUstid: 'ATU12345678',
408
+ firmenname: 'Musterhaus GmbH & Co KG',
409
+ strasse: 'Musterstrasse 22',
410
+ plz: '12345',
411
+ ort: 'musterort'
412
+ };
413
+ ```
414
+
415
+ ## Changelog
416
+
417
+ Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
418
+
419
+ ## Contributing
420
+
421
+ Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
422
+
423
+ ## Security Vulnerabilities
424
+
425
+ If you discover any security-related issues, please email [open-source@rechtlogisch.de](mailto:open-source@rechtlogisch.de) instead of using the issue tracker.
426
+
427
+ ## Credits
428
+
429
+ - [Krzysztof Tomasz Zembrowski](https://github.com/zembrowski)
430
+ - [All Contributors](../../contributors)
431
+
432
+ ## License
433
+
434
+ The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
@@ -0,0 +1,67 @@
1
+ import { ApiStatusMessage, StatusMessage } from './types';
2
+ export interface ApiDocsInfo {
3
+ title: string;
4
+ description: string;
5
+ version: string;
6
+ }
7
+ export interface UpdateCheckResult {
8
+ hasUpdate: boolean;
9
+ currentVersion?: string;
10
+ latestVersion?: string;
11
+ downloadUrl?: string;
12
+ }
13
+ export interface StatusMessageDiff {
14
+ added: ApiStatusMessage[];
15
+ removed: ApiStatusMessage[];
16
+ modified: Array<{
17
+ status: string;
18
+ old: ApiStatusMessage;
19
+ new: ApiStatusMessage;
20
+ }>;
21
+ }
22
+ /**
23
+ * API Update utilities for eVatR API
24
+ */
25
+ export declare class EvatrApiUpdater {
26
+ private static readonly API_DOCS_URL;
27
+ private static readonly DOCS_DIR;
28
+ /**
29
+ * Check for new API documentation version
30
+ */
31
+ static checkApiDocsUpdate(): Promise<UpdateCheckResult>;
32
+ /**
33
+ * Download and save new API documentation
34
+ */
35
+ static downloadApiDocs(): Promise<string>;
36
+ /**
37
+ * Check for new status messages
38
+ */
39
+ static checkStatusMessagesUpdate(): Promise<UpdateCheckResult & {
40
+ diff?: StatusMessageDiff;
41
+ }>;
42
+ /**
43
+ * Download and save new status messages
44
+ */
45
+ static downloadStatusMessages(): Promise<string>;
46
+ /**
47
+ * Compare two sets of status messages and return differences
48
+ */
49
+ private static compareStatusMessages;
50
+ /**
51
+ * Print status message differences in a readable format
52
+ */
53
+ static printStatusMessageDiff(diff: StatusMessageDiff): void;
54
+ /**
55
+ * Update constants.ts file with new status messages
56
+ */
57
+ static updateConstantsFile(statusMessages: StatusMessage[]): Promise<void>;
58
+ /**
59
+ * Run complete update check and download if needed
60
+ */
61
+ static checkAndUpdateAll(): Promise<void>;
62
+ /**
63
+ * Update constants from a downloaded status messages file
64
+ */
65
+ static updateConstantsFromFile(filepath: string): Promise<void>;
66
+ }
67
+ //# sourceMappingURL=api-updater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-updater.d.ts","sourceRoot":"","sources":["../src/api-updater.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,gBAAgB,CAAC;QACtB,GAAG,EAAE,gBAAgB,CAAC;KACvB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAA8B;IAClE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAY;IAE5C;;OAEG;WACU,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAwC7D;;OAEG;WACU,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IA4B/C;;OAEG;WACU,yBAAyB,IAAI,OAAO,CAAC,iBAAiB,GAAG;QAAE,IAAI,CAAC,EAAE,iBAAiB,CAAA;KAAE,CAAC;IAqCnG;;OAEG;WACU,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IA2BtD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA4BpC;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IA+B5D;;OAEG;WACU,mBAAmB,CAAC,cAAc,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgChF;;OAEG;WACU,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC/C;;OAEG;WACU,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBtE"}