@taxora/sdk 1.2.0 → 1.3.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.d.cts CHANGED
@@ -160,8 +160,24 @@ declare function toComplianceEnrollmentStatus(value: unknown): ComplianceEnrollm
160
160
  declare function describeComplianceEnrollmentStatus(status: ComplianceEnrollmentStatus): string;
161
161
 
162
162
  /**
163
- * A compliance enrollment — the merchant's provisioned e-reporting account for
164
- * one reporting country/regime (GET/POST /compliance/enrollments).
163
+ * The compliance service an enrollment books for its country: French DGFiP
164
+ * e-reporting, or e-invoicing (e.g. Norway EHF / Peppol BIS 3.0). Each country
165
+ * and service is unlocked and billed separately.
166
+ */
167
+ declare const ComplianceService: {
168
+ readonly E_REPORTING: "e_reporting";
169
+ readonly E_INVOICING: "e_invoicing";
170
+ readonly UNKNOWN: "unknown";
171
+ };
172
+ type ComplianceService = (typeof ComplianceService)[keyof typeof ComplianceService];
173
+ /** Tolerant coercion: unrecognized values become `unknown` instead of throwing. */
174
+ declare function toComplianceService(value: unknown): ComplianceService;
175
+ declare function describeComplianceService(service: ComplianceService): string;
176
+
177
+ /**
178
+ * A compliance enrollment — the merchant's provisioned account for one country
179
+ * and service (GET/POST /compliance/enrollments), e.g. France e-reporting
180
+ * (regime "dgfip_flux10") or Norway e-invoicing (regime "peppol_bis3").
165
181
  */
166
182
  declare class ComplianceEnrollment {
167
183
  readonly id: number;
@@ -183,9 +199,13 @@ declare class ComplianceEnrollment {
183
199
  readonly autoSend: boolean;
184
200
  readonly createdAt: string | null;
185
201
  readonly updatedAt: string | null;
202
+ /** Booked service ("e_reporting" / "e_invoicing"); `unknown` when an older server omits it. */
203
+ readonly service: ComplianceService;
186
204
  constructor(id: number, companyId: number, country: string, regime: string, provider: string, status: ComplianceEnrollmentStatus, statusLabel: string, statusError: string | null, providerAccountId: string | null, taxId: string | null, companyRegisterId: string | null, companyRegisterScheme: string | null, regimeConfig: Record<string, unknown> | null,
187
205
  /** First date transactions are reported for (YYYY-MM-DD). */
188
- reportingStartDate: string | null, notificationEmail: string | null, autoSend: boolean, createdAt: string | null, updatedAt: string | null);
206
+ reportingStartDate: string | null, notificationEmail: string | null, autoSend: boolean, createdAt: string | null, updatedAt: string | null,
207
+ /** Booked service ("e_reporting" / "e_invoicing"); `unknown` when an older server omits it. */
208
+ service?: ComplianceService);
189
209
  static fromArray(data: Record<string, unknown>): ComplianceEnrollment;
190
210
  }
191
211
 
@@ -264,6 +284,17 @@ declare class ComplianceTaxReportPage implements Iterable<ComplianceTaxReport> {
264
284
  get length(): number;
265
285
  }
266
286
 
287
+ /** Kind of document a compliance transaction represents. */
288
+ declare const ComplianceDocumentType: {
289
+ readonly INVOICE: "invoice";
290
+ readonly CREDIT_NOTE: "credit_note";
291
+ readonly UNKNOWN: "unknown";
292
+ };
293
+ type ComplianceDocumentType = (typeof ComplianceDocumentType)[keyof typeof ComplianceDocumentType];
294
+ /** Tolerant coercion: unrecognized values become `unknown` instead of throwing. */
295
+ declare function toComplianceDocumentType(value: unknown): ComplianceDocumentType;
296
+ declare function describeComplianceDocumentType(type: ComplianceDocumentType): string;
297
+
267
298
  declare const ComplianceTransactionState: {
268
299
  readonly PENDING: "pending";
269
300
  readonly SENDING: "sending";
@@ -289,8 +320,30 @@ type ComplianceTransactionType = (typeof ComplianceTransactionType)[keyof typeof
289
320
  declare function toComplianceTransactionType(value: unknown): ComplianceTransactionType;
290
321
  declare function describeComplianceTransactionType(type: ComplianceTransactionType): string;
291
322
 
323
+ /** One tax of a stored invoice line (provider shape, as recorded at creation/update). */
324
+ interface ComplianceTransactionInvoiceLineTax {
325
+ name: string;
326
+ percent: number | null;
327
+ category: string | null;
328
+ /** VATEX exemption code for category "E". */
329
+ comment: string | null;
330
+ }
331
+ /** One stored invoice line (`provider_payload.invoice.invoice_lines_attributes`). */
332
+ interface ComplianceTransactionInvoiceLine {
333
+ description: string;
334
+ quantity: number | null;
335
+ /** Unit price as a precision-safe decimal string. */
336
+ price: string;
337
+ /** UN/ECE unit code, e.g. 9 (each). */
338
+ unit: number | null;
339
+ taxes: ComplianceTransactionInvoiceLineTax[];
340
+ }
292
341
  /**
293
- * A recorded e-reporting transaction (GET/POST /compliance/transactions).
342
+ * A recorded compliance transaction (GET/POST /compliance/transactions) — an
343
+ * e-reported transaction (France) or an e-invoice / credit note (Norway).
344
+ *
345
+ * The e-invoicing fields at the end of the constructor are optional so DTOs
346
+ * built from older servers (or by hand) stay valid.
294
347
  */
295
348
  declare class ComplianceTransaction {
296
349
  readonly id: number;
@@ -322,11 +375,49 @@ declare class ComplianceTransaction {
322
375
  readonly taxReport: ComplianceTaxReport | undefined;
323
376
  readonly createdAt: string | null;
324
377
  readonly updatedAt: string | null;
378
+ /** Buyer's company register id (Norway: 9-digit organisation number). */
379
+ readonly counterpartyRegisterId: string | null;
380
+ readonly counterpartyAddress: string | null;
381
+ readonly counterpartyCity: string | null;
382
+ readonly counterpartyPostalcode: string | null;
383
+ readonly counterpartyEmail: string | null;
384
+ readonly buyerReference: string | null;
385
+ /** "invoice" or "credit_note" (older servers without the field → "invoice"). */
386
+ readonly documentType: ComplianceDocumentType;
387
+ /** Number of the invoice a credit note corrects. */
388
+ readonly amendedNumber: string | null;
389
+ /** Date of the invoice a credit note corrects (YYYY-MM-DD). */
390
+ readonly amendedDate: string | null;
391
+ /**
392
+ * Latest provider-side delivery state (e.g. "sent", "accepted", "refused",
393
+ * "paid") — richer than `state` for e-invoicing, where delivery continues
394
+ * after submission. Free-form string; null until the provider reports one.
395
+ */
396
+ readonly providerState: string | null;
397
+ /** The stored invoice lines (empty when the server does not include them). */
398
+ readonly invoiceLines: ComplianceTransactionInvoiceLine[];
325
399
  constructor(id: number, companyId: number, complianceEnrollmentId: number, country: string, regime: string, transactionType: ComplianceTransactionType, transactionTypeLabel: string, state: ComplianceTransactionState, stateLabel: string, invoiceNumber: string,
326
400
  /** Invoice date (YYYY-MM-DD). */
327
401
  invoiceDate: string | null, dueDate: string | null, currency: string, subtotal: string, taxAmount: string, total: string, counterpartyName: string | null, counterpartyCountry: string | null, counterpartyVatNumber: string | null, isPaid: boolean, paidAt: string | null, providerInvoiceId: string | null, submissionError: string | null, reportedAt: string | null,
328
402
  /** Associated DGFiP tax report; undefined when the API did not include it. */
329
- taxReport: ComplianceTaxReport | undefined, createdAt: string | null, updatedAt: string | null);
403
+ taxReport: ComplianceTaxReport | undefined, createdAt: string | null, updatedAt: string | null,
404
+ /** Buyer's company register id (Norway: 9-digit organisation number). */
405
+ counterpartyRegisterId?: string | null, counterpartyAddress?: string | null, counterpartyCity?: string | null, counterpartyPostalcode?: string | null, counterpartyEmail?: string | null, buyerReference?: string | null,
406
+ /** "invoice" or "credit_note" (older servers without the field → "invoice"). */
407
+ documentType?: ComplianceDocumentType,
408
+ /** Number of the invoice a credit note corrects. */
409
+ amendedNumber?: string | null,
410
+ /** Date of the invoice a credit note corrects (YYYY-MM-DD). */
411
+ amendedDate?: string | null,
412
+ /**
413
+ * Latest provider-side delivery state (e.g. "sent", "accepted", "refused",
414
+ * "paid") — richer than `state` for e-invoicing, where delivery continues
415
+ * after submission. Free-form string; null until the provider reports one.
416
+ */
417
+ providerState?: string | null,
418
+ /** The stored invoice lines (empty when the server does not include them). */
419
+ invoiceLines?: ComplianceTransactionInvoiceLine[]);
420
+ get isCreditNote(): boolean;
330
421
  static fromArray(data: Record<string, unknown>): ComplianceTransaction;
331
422
  }
332
423
 
@@ -365,6 +456,93 @@ declare class ImportResult {
365
456
  static fromArray(data: Record<string, unknown>): ImportResult;
366
457
  }
367
458
 
459
+ /**
460
+ * Outcome of a Peppol directory lookup (GET /compliance/peppol-lookup). The
461
+ * directory resolves asynchronously — `pending` means ask again in a few seconds.
462
+ */
463
+ declare const PeppolLookupStatus: {
464
+ readonly REACHABLE: "reachable";
465
+ readonly NOT_REACHABLE: "not_reachable";
466
+ readonly PENDING: "pending";
467
+ readonly UNKNOWN: "unknown";
468
+ };
469
+ type PeppolLookupStatus = (typeof PeppolLookupStatus)[keyof typeof PeppolLookupStatus];
470
+ /** Tolerant coercion: unrecognized values become `unknown` instead of throwing. */
471
+ declare function toPeppolLookupStatus(value: unknown): PeppolLookupStatus;
472
+ declare function describePeppolLookupStatus(status: PeppolLookupStatus): string;
473
+
474
+ /**
475
+ * Whether a participant can receive e-invoices over Peppol
476
+ * (GET /compliance/peppol-lookup). For Norway, `reachable === true` means the
477
+ * buyer is registered in ELMA and must receive an EHF e-invoice.
478
+ */
479
+ declare class PeppolLookupResult {
480
+ readonly status: PeppolLookupStatus;
481
+ /** null while the lookup is still `pending`. */
482
+ readonly reachable: boolean | null;
483
+ readonly country: string;
484
+ /** Peppol identifier scheme, e.g. "0192" for Norwegian organisation numbers. */
485
+ readonly scheme: string;
486
+ /** Participant identifier, e.g. the organisation number. */
487
+ readonly id: string;
488
+ /** Peppol document types the participant accepts, e.g. "xml.ubl.invoice.bis3". */
489
+ readonly documentTypes: string[];
490
+ readonly transportTypeCode: string | null;
491
+ readonly checkedAt: string | null;
492
+ constructor(status: PeppolLookupStatus,
493
+ /** null while the lookup is still `pending`. */
494
+ reachable: boolean | null, country: string,
495
+ /** Peppol identifier scheme, e.g. "0192" for Norwegian organisation numbers. */
496
+ scheme: string,
497
+ /** Participant identifier, e.g. the organisation number. */
498
+ id: string,
499
+ /** Peppol document types the participant accepts, e.g. "xml.ubl.invoice.bis3". */
500
+ documentTypes: string[], transportTypeCode: string | null, checkedAt: string | null);
501
+ /** True while the directory is still resolving — ask again in a few seconds. */
502
+ get isPending(): boolean;
503
+ static fromArray(data: Record<string, unknown>): PeppolLookupResult;
504
+ }
505
+
506
+ /**
507
+ * A company from a national company register (GET /compliance/registry-lookup) —
508
+ * for Norway the Brønnøysund Enhetsregisteret. Maps onto the Norway enrollment
509
+ * input and the buyer fields of a Norwegian e-invoice.
510
+ */
511
+ declare class RegistryCompany {
512
+ /** 9-digit Norwegian organisation number. */
513
+ readonly orgNumber: string;
514
+ readonly companyName: string;
515
+ /** Legal form, e.g. "AS" or "ASA". */
516
+ readonly organisationForm: string | null;
517
+ /** Registered for VAT (Merverdiavgiftsregisteret). */
518
+ readonly vatRegistered: boolean;
519
+ /** "NO…MVA" VAT number; null when not VAT-registered. */
520
+ readonly vatNumber: string | null;
521
+ /** Registered in Foretaksregisteret (adds "Foretaksregisteret" to invoices). */
522
+ readonly enterpriseRegister: boolean;
523
+ readonly bankrupt: boolean;
524
+ readonly underLiquidation: boolean;
525
+ readonly address: string | null;
526
+ readonly postalcode: string | null;
527
+ readonly city: string | null;
528
+ /** 2-char ISO 3166-1 alpha-2 code, e.g. "NO". */
529
+ readonly country: string;
530
+ constructor(
531
+ /** 9-digit Norwegian organisation number. */
532
+ orgNumber: string, companyName: string,
533
+ /** Legal form, e.g. "AS" or "ASA". */
534
+ organisationForm: string | null,
535
+ /** Registered for VAT (Merverdiavgiftsregisteret). */
536
+ vatRegistered: boolean,
537
+ /** "NO…MVA" VAT number; null when not VAT-registered. */
538
+ vatNumber: string | null,
539
+ /** Registered in Foretaksregisteret (adds "Foretaksregisteret" to invoices). */
540
+ enterpriseRegister: boolean, bankrupt: boolean, underLiquidation: boolean, address: string | null, postalcode: string | null, city: string | null,
541
+ /** 2-char ISO 3166-1 alpha-2 code, e.g. "NO". */
542
+ country: string);
543
+ static fromArray(data: Record<string, unknown>): RegistryCompany;
544
+ }
545
+
368
546
  /**
369
547
  * DTOs for the e-reporting revenue statistics endpoint
370
548
  * (GET /compliance/revenue-statistics).
@@ -481,6 +659,8 @@ type EReportingInterval = 'day' | 'week' | 'month';
481
659
  type ComplianceEnterpriseSize = 'micro' | 'pme' | 'eti' | 'ge';
482
660
  /** Type of operations the enrolled company performs. */
483
661
  type ComplianceTypeOperation = 'services' | 'goods' | 'mixed';
662
+ /** Services accepted on the request side (the tolerant `unknown` is response-only). */
663
+ type ComplianceRequestService = Exclude<ComplianceService, 'unknown'>;
484
664
  /** Transaction types accepted on the request side (the tolerant `unknown` is response-only). */
485
665
  type ComplianceTransactionRequestType = Exclude<ComplianceTransactionType, 'unknown'>;
486
666
  /** Transaction states accepted as filters (the tolerant `unknown` is response-only). */
@@ -495,9 +675,15 @@ interface RevenueStatisticsFilters {
495
675
  transactionType?: ComplianceTransactionRequestType;
496
676
  state?: ComplianceTransactionRequestState;
497
677
  }
678
+ /**
679
+ * France (DGFiP e-reporting) enrollment — the original createEnrollment() input.
680
+ * For Norway use {@link CreateNorwayEnrollmentInput} (or createNorwayEnrollment()).
681
+ */
498
682
  interface CreateComplianceEnrollmentInput {
499
- /** Reporting country (2-char ISO 3166-1 alpha-2). Defaults server-side (FR). */
683
+ /** Reporting country (2-char ISO 3166-1 alpha-2). Defaults server-side (FR). "NO" selects the Norway input. */
500
684
  country?: string;
685
+ /** Service to book. Defaults server-side to the country's default service (FR: "e_reporting"). */
686
+ service?: ComplianceRequestService;
501
687
  /** Compliance regime, e.g. "dgfip_flux10". Defaults server-side. */
502
688
  regime?: string;
503
689
  /** 14-digit SIRET. Required unless `siren` is set. */
@@ -521,6 +707,45 @@ interface CreateComplianceEnrollmentInput {
521
707
  /** When false, only the provider account is created — the DGFiP regime is NOT activated. Defaults to true server-side. */
522
708
  autoActivate?: boolean;
523
709
  }
710
+ /**
711
+ * Norway e-invoicing (EHF / Peppol BIS 3.0) enrollment: registers the company
712
+ * as a Peppol participant so it can send (and optionally receive) e-invoices.
713
+ * Prefill it from registryLookup('NO', …).
714
+ */
715
+ interface CreateNorwayEnrollmentInput {
716
+ country: 'NO';
717
+ /** Service to book. Defaults server-side to "e_invoicing" (the only service for NO). */
718
+ service?: ComplianceRequestService;
719
+ /** Compliance regime. Defaults server-side ("peppol_bis3"). */
720
+ regime?: string;
721
+ /**
722
+ * 9-digit Norwegian organisation number (mod-11 check digit). Spaces, a "NO"
723
+ * prefix and an "MVA" suffix are accepted and stripped before sending.
724
+ */
725
+ orgNumber: string;
726
+ companyName: string;
727
+ address: string;
728
+ city: string;
729
+ postalcode: string;
730
+ /** Notification email for the provider account. */
731
+ email: string;
732
+ vatNumber?: string;
733
+ province?: string;
734
+ /** Registered in Merverdiavgiftsregisteret (adds "MVA" to invoices). Defaults to true server-side. */
735
+ vatRegistered?: boolean;
736
+ /** Registered in Foretaksregisteret (adds "Foretaksregisteret" to invoices). Defaults to false server-side. */
737
+ enterpriseRegister?: boolean;
738
+ /** Also register to RECEIVE e-invoices over Peppol. Defaults to false server-side. */
739
+ reception?: boolean;
740
+ /** Country of the legal entity when it differs from NO (2-char ISO 3166-1 alpha-2). */
741
+ legalCountry?: string;
742
+ /** Optional first date transactions are recorded for (Date or strict YYYY-MM-DD). */
743
+ reportingStartDate?: Date | string;
744
+ /** When false, only the provider account is created — the Peppol registration is NOT activated. Defaults to true server-side. */
745
+ autoActivate?: boolean;
746
+ }
747
+ /** createNorwayEnrollment() input — the Norway input without the fixed `country`. */
748
+ type NorwayEnrollmentInput = Omit<CreateNorwayEnrollmentInput, 'country'>;
524
749
  interface ComplianceInvoiceTaxInput {
525
750
  /** Tax designation, e.g. "TVA". */
526
751
  name: string;
@@ -540,7 +765,34 @@ interface ComplianceInvoiceLineInput {
540
765
  /** At least one tax per line. */
541
766
  taxes: ComplianceInvoiceTaxInput[];
542
767
  }
543
- interface CreateComplianceTransactionInput {
768
+ /**
769
+ * Buyer and document fields interpreted per country. For Norway (EHF / Peppol)
770
+ * `counterpartyRegisterId` (the buyer's organisation number) and
771
+ * `counterpartyName` are required unless `providerContactId` is set, the
772
+ * transaction type must be "b2b_domestic_outbound", and a credit note needs
773
+ * `amendedNumber`. The SDK does not know the enrollment's country — those rules
774
+ * are enforced server-side (422).
775
+ */
776
+ interface ComplianceTransactionBuyerInput {
777
+ /** Buyer's company register id (Norway: 9-digit organisation number; "NO…MVA" is accepted). Max 30 chars. */
778
+ counterpartyRegisterId?: string;
779
+ counterpartyAddress?: string;
780
+ counterpartyCity?: string;
781
+ counterpartyPostalcode?: string;
782
+ /** Buyer's email address. */
783
+ counterpartyEmail?: string;
784
+ /** Buyer reference (Peppol BuyerReference); max 100 chars. Norway defaults it to the buyer's org number. */
785
+ buyerReference?: string;
786
+ /** Issue the document as a credit note. */
787
+ isCreditNote?: boolean;
788
+ /** Number of the invoice a credit note corrects (max 50 chars). */
789
+ amendedNumber?: string;
790
+ /** Date of the invoice a credit note corrects (Date or strict YYYY-MM-DD). */
791
+ amendedDate?: Date | string;
792
+ /** Free-text note printed on the invoice (max 1000 chars). */
793
+ extraInfo?: string;
794
+ }
795
+ interface CreateComplianceTransactionInput extends ComplianceTransactionBuyerInput {
544
796
  complianceEnrollmentId: number;
545
797
  transactionType: ComplianceTransactionRequestType;
546
798
  invoiceNumber: string;
@@ -567,7 +819,7 @@ interface CreateComplianceTransactionInput {
567
819
  /** When false, the transaction is only recorded — submission is deferred. Defaults to true server-side. */
568
820
  submitNow?: boolean;
569
821
  }
570
- interface UpdateComplianceTransactionInput {
822
+ interface UpdateComplianceTransactionInput extends ComplianceTransactionBuyerInput {
571
823
  transactionType?: ComplianceTransactionRequestType;
572
824
  invoiceNumber?: string;
573
825
  invoiceDate?: Date | string;
@@ -596,6 +848,10 @@ interface ComplianceTransactionFilters {
596
848
  dateTo?: Date | string;
597
849
  state?: ComplianceTransactionRequestState;
598
850
  transactionType?: ComplianceTransactionRequestType;
851
+ /** Only transactions of this enrollment. */
852
+ complianceEnrollmentId?: number;
853
+ /** Only transactions of this country (2-char ISO 3166-1 alpha-2). */
854
+ country?: string;
599
855
  page?: number;
600
856
  /** Page size (1-100, default 25 server-side). */
601
857
  perPage?: number;
@@ -608,16 +864,27 @@ interface EReportingAccessRequestInput {
608
864
  message?: string;
609
865
  /** Locale for the confirmation mail, e.g. "de" or "en". */
610
866
  language?: string;
867
+ /** The service being requested. Defaults server-side to "e_reporting". */
868
+ service?: ComplianceRequestService;
869
+ /** The countries the service is requested for (2-char ISO codes), e.g. ["NO"]. */
870
+ countries?: string[];
611
871
  }
612
872
  /**
613
- * E-Reporting / Compliance (DGFiP Flux 10) endpoints.
873
+ * E-Reporting / Compliance endpoints (per-country services).
614
874
  *
615
- * Typical flow: sireneLookup() to prefill company data, createEnrollment() to
616
- * provision the provider account, then createTransaction() / importTransactions()
617
- * to record invoices and listTaxReports() to track their DGFiP lifecycle.
875
+ * - France — e-reporting (DGFiP Flux 10): sireneLookup() to prefill company
876
+ * data, createEnrollment() to provision the provider account, then
877
+ * createTransaction() / importTransactions() to record invoices and
878
+ * listTaxReports() to track their DGFiP lifecycle.
879
+ * - Norway — e-invoicing (EHF / Peppol BIS 3.0): registryLookup('NO', …) to
880
+ * prefill company/buyer data, createNorwayEnrollment() to register as a Peppol
881
+ * participant, peppolLookup('NO', …) to check a buyer is reachable, then
882
+ * createTransaction() to send invoices and credit notes.
618
883
  *
619
- * All routes except requestEReportingAccess() require an active E-Reporting
620
- * subscription / feature grant on the account.
884
+ * Each country/service is unlocked (and billed) separately; enrolling for a
885
+ * service the company does not have yields a 403 with code `service_not_active`.
886
+ * All routes except requestEReportingAccess() require compliance access on the
887
+ * account.
621
888
  */
622
889
  declare class EReportingEndpoint {
623
890
  private readonly baseUrl;
@@ -628,14 +895,26 @@ declare class EReportingEndpoint {
628
895
  constructor(baseUrl: string, apiKey: string, tokenStorage: TokenStorageInterface, httpClient: HttpClientInterface, retryPolicy?: RetryPolicy);
629
896
  /**
630
897
  * Create a compliance enrollment and provision the provider account. By
631
- * default the DGFiP regime is activated right away; pass `autoActivate: false`
898
+ * default the country regime is activated right away (France: DGFiP tax
899
+ * report setting; Norway: Peppol registration); pass `autoActivate: false`
632
900
  * to only create the account.
633
901
  *
634
- * On provider failure the API responds 502 (mapped to an HttpException) and
635
- * the enrollment is persisted in `error_account`/`error_activation` state so
902
+ * The input shape depends on `country`: omitted/"FR" takes the France input
903
+ * (unchanged, backwards compatible), "NO" the Norway input — see also the
904
+ * createNorwayEnrollment() shortcut.
905
+ *
906
+ * Errors: 403 (HttpException, body code `service_not_active`) when the company
907
+ * lacks the requested service; on provider failure 502 (HttpException) — the
908
+ * enrollment is then persisted in `error_account`/`error_activation` state so
636
909
  * provisioning can be retried.
637
910
  */
638
- createEnrollment(input: CreateComplianceEnrollmentInput): Promise<ComplianceEnrollment>;
911
+ createEnrollment(input: CreateComplianceEnrollmentInput | CreateNorwayEnrollmentInput): Promise<ComplianceEnrollment>;
912
+ /**
913
+ * Enroll the company for Norway e-invoicing (EHF / Peppol BIS 3.0) — shortcut
914
+ * for createEnrollment({ country: 'NO', ... }). The organisation number is
915
+ * checked (mod-11) and normalized to 9 digits before sending.
916
+ */
917
+ createNorwayEnrollment(input: NorwayEnrollmentInput): Promise<ComplianceEnrollment>;
639
918
  /** Paginated list of the company's enrollments (newest first). `perPage` is capped at 100 server-side. */
640
919
  listEnrollments(page?: number, perPage?: number): Promise<ComplianceEnrollmentPage>;
641
920
  /** Get a single enrollment by id. */
@@ -648,6 +927,31 @@ declare class EReportingEndpoint {
648
927
  * government API); exceeding it yields a 429 (mapped to an HttpException).
649
928
  */
650
929
  sireneLookup(q: string): Promise<SireneLookupResult>;
930
+ /**
931
+ * Look up companies in a national company register — currently Norway
932
+ * (Brønnøysund Enhetsregisteret). `q` is an organisation number, a "NO…MVA"
933
+ * VAT number or a company name; an exact number match yields one result.
934
+ * Ideal for prefilling createNorwayEnrollment() and the buyer fields of an
935
+ * e-invoice. For France use sireneLookup().
936
+ *
937
+ * Errors: 404 (HttpException) when nothing is found, 422 (ValidationException)
938
+ * on invalid input / unsupported country, 429 (HttpException) when the
939
+ * per-user rate limit (30/min) is exceeded.
940
+ */
941
+ registryLookup(country: string, q: string): Promise<RegistryCompany[]>;
942
+ /**
943
+ * Check whether a participant (typically the buyer) can receive e-invoices
944
+ * over Peppol. For Norway pass the organisation number (scheme defaults to
945
+ * "0192"): `reachable === true` means the buyer is registered in ELMA and must
946
+ * receive an EHF e-invoice. The directory resolves asynchronously —
947
+ * `status === 'pending'` (`reachable === null`) means ask again in a few
948
+ * seconds. Free of charge; definite answers are cached for 24h server-side.
949
+ *
950
+ * A Norwegian organisation number is checked (mod-11) and normalized before
951
+ * sending. Errors: 422 (ValidationException) on invalid input, 502
952
+ * (HttpException) on provider failure.
953
+ */
954
+ peppolLookup(country: string, id: string, scheme?: string): Promise<PeppolLookupResult>;
651
955
  /**
652
956
  * Record and (by default) submit a Flux 10 transaction. Pass `submitNow: false`
653
957
  * to only record it — submission can be triggered later via submitTransaction().
@@ -663,7 +967,7 @@ declare class EReportingEndpoint {
663
967
  * On provider failure the API responds 502 (mapped to an HttpException).
664
968
  */
665
969
  createTransaction(input: CreateComplianceTransactionInput): Promise<ComplianceTransaction>;
666
- /** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type. */
970
+ /** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country. */
667
971
  listTransactions(filters?: ComplianceTransactionFilters): Promise<ComplianceTransactionPage>;
668
972
  /** Get a single transaction by id (includes its tax report when one exists). */
669
973
  getTransaction(id: number): Promise<ComplianceTransaction>;
@@ -720,11 +1024,25 @@ declare class EReportingEndpoint {
720
1024
  */
721
1025
  requestEReportingAccess(input?: EReportingAccessRequestInput): Promise<void>;
722
1026
  private validateEnrollmentInput;
1027
+ private isNorwayEnrollmentInput;
1028
+ /** Validates the Norway input and builds its wire body (org number normalized to 9 digits). */
1029
+ private buildNorwayEnrollmentBody;
1030
+ private createEnrollmentFromBody;
1031
+ private validateService;
1032
+ private validateEmail;
1033
+ /** Lookup routes take a 2-letter country; the API expects it upper-case. */
1034
+ private normalizeLookupCountry;
723
1035
  private validateId;
724
1036
  private validateTransactionType;
725
1037
  private validateInvoiceNumber;
726
1038
  private validateInvoiceLines;
727
1039
  private validateOptionalCodes;
1040
+ /**
1041
+ * Format checks for the buyer/document fields. Country rules (e.g. the Norway
1042
+ * org number being required) depend on the enrollment and stay server-side;
1043
+ * a register id is only check-digit validated when the buyer is Norwegian.
1044
+ */
1045
+ private validateBuyerFields;
728
1046
  private buildInvoiceLines;
729
1047
  /** Applies the optional scalar fields shared by create and update. */
730
1048
  private applyOptionalTransactionFields;
@@ -1343,11 +1661,170 @@ declare const ApiVersion: {
1343
1661
  };
1344
1662
  type ApiVersion = (typeof ApiVersion)[keyof typeof ApiVersion];
1345
1663
 
1664
+ /**
1665
+ * Norwegian organisation number (organisasjonsnummer): 9 digits, the last one a
1666
+ * modulus-11 check digit (weights 3,2,7,6,5,4,3,2). It is also the Peppol
1667
+ * participant identifier under scheme 0192 and — with the "NO" prefix and "MVA"
1668
+ * suffix — the Norwegian VAT number.
1669
+ *
1670
+ * Mirrors the backend's validation, so invalid numbers are rejected before a
1671
+ * request is sent.
1672
+ */
1673
+ declare const NorwegianOrgNumber: {
1674
+ /** Peppol identifier scheme for Norwegian organisation numbers. */
1675
+ readonly PEPPOL_SCHEME: "0192";
1676
+ /**
1677
+ * Strips whitespace, dots, dashes, a "0192:" Peppol scheme prefix, the "NO"
1678
+ * prefix and the "MVA" suffix: "NO 923 609 016 MVA", "923609016MVA" and
1679
+ * "923 609 016" all become "923609016". Does not validate.
1680
+ */
1681
+ readonly normalize: (value: string | null | undefined) => string;
1682
+ /** True when the (normalized) value is 9 digits with a valid mod-11 check digit. */
1683
+ readonly isValid: (value: string | null | undefined) => boolean;
1684
+ /** "NO923609016MVA" — the Norwegian VAT number of an MVA-registered entity. Does not validate. */
1685
+ readonly toVatNumber: (value: string) => string;
1686
+ };
1687
+
1346
1688
  declare class TaxoraException extends Error {
1347
1689
  readonly context: Record<string, unknown>;
1348
1690
  constructor(message: string, context?: Record<string, unknown>);
1349
1691
  }
1350
1692
 
1693
+ /**
1694
+ * Typed shapes of the JSON bodies Taxora POSTs to your webhook endpoint.
1695
+ *
1696
+ * Every event shares the same envelope ({@link WebhookEventEnvelope}); `event` narrows `data.object`:
1697
+ *
1698
+ * ```ts
1699
+ * const event = constructWebhookEvent(rawBody, header, secret);
1700
+ * if (event.event === 'vat.validated') {
1701
+ * event.data.object.vat_uid; // string
1702
+ * }
1703
+ * ```
1704
+ */
1705
+ type WebhookEventType = 'vat.validated' | 'vat.state_changed' | 'compliance.ledger.state_changed' | 'compliance.transaction.state_changed' | 'enrichment.completed' | 'enrichment.updated' | 'webhook.test';
1706
+ interface WebhookEventEnvelope<TEvent extends string, TObject> {
1707
+ /** Delivery UUID — identical to the `Taxora-Webhook-Id` header and stable across retries. Use it to dedupe. */
1708
+ id: string;
1709
+ event: TEvent;
1710
+ /** Unix seconds when the event was created (not the delivery attempt — that is `t` in the signature). */
1711
+ timestamp: number;
1712
+ data: {
1713
+ object: TObject;
1714
+ };
1715
+ }
1716
+ interface VatWebhookObject {
1717
+ id: number;
1718
+ vat_uid: string;
1719
+ /** A VatState value, e.g. `valid`, `invalid`. */
1720
+ state: string;
1721
+ company_name: string | null;
1722
+ country_code: string | null;
1723
+ checked_at: string | null;
1724
+ }
1725
+ interface ComplianceLedgerWebhookObject {
1726
+ id: number;
1727
+ state: string;
1728
+ ledger_type: string | null;
1729
+ ledger_date: string | null;
1730
+ }
1731
+ interface ComplianceTransactionWebhookObject {
1732
+ id: number;
1733
+ state: string;
1734
+ provider_state: string | null;
1735
+ country: string | null;
1736
+ invoice_number: string | null;
1737
+ }
1738
+ /** Raw Smart Enrichment rows — wrap them with `SmartEnrichmentResource.fromArray()` for a typed DTO. */
1739
+ interface EnrichmentCompletedWebhookObject {
1740
+ jobId: string;
1741
+ status: string;
1742
+ itemCount: number;
1743
+ foundCount: number;
1744
+ results: Record<string, unknown>[];
1745
+ }
1746
+ interface EnrichmentUpdatedWebhookObject {
1747
+ jobId: string;
1748
+ status: string;
1749
+ itemCount: number;
1750
+ foundCount: number;
1751
+ /** Zero-based index of the row that changed, matching `results[rowIndex]` of enrichment.completed. */
1752
+ rowIndex: number;
1753
+ result: Record<string, unknown> | null;
1754
+ }
1755
+ interface TestWebhookObject {
1756
+ message: string;
1757
+ }
1758
+ type VatValidatedEvent = WebhookEventEnvelope<'vat.validated', VatWebhookObject>;
1759
+ type VatStateChangedEvent = WebhookEventEnvelope<'vat.state_changed', VatWebhookObject>;
1760
+ type ComplianceLedgerStateChangedEvent = WebhookEventEnvelope<'compliance.ledger.state_changed', ComplianceLedgerWebhookObject>;
1761
+ type ComplianceTransactionStateChangedEvent = WebhookEventEnvelope<'compliance.transaction.state_changed', ComplianceTransactionWebhookObject>;
1762
+ type EnrichmentCompletedEvent = WebhookEventEnvelope<'enrichment.completed', EnrichmentCompletedWebhookObject>;
1763
+ type EnrichmentUpdatedEvent = WebhookEventEnvelope<'enrichment.updated', EnrichmentUpdatedWebhookObject>;
1764
+ type WebhookTestEvent = WebhookEventEnvelope<'webhook.test', TestWebhookObject>;
1765
+ /** Discriminated union of every event Taxora sends. Switch on `event` to narrow `data.object`. */
1766
+ type TaxoraWebhookEvent = VatValidatedEvent | VatStateChangedEvent | ComplianceLedgerStateChangedEvent | ComplianceTransactionStateChangedEvent | EnrichmentCompletedEvent | EnrichmentUpdatedEvent | WebhookTestEvent;
1767
+
1768
+ /** Name of the HTTP header that carries the signature. Node lower-cases it: `req.headers['taxora-signature']`. */
1769
+ declare const WEBHOOK_SIGNATURE_HEADER = "Taxora-Signature";
1770
+ /** Name of the HTTP header that carries the delivery UUID (stable across retries). */
1771
+ declare const WEBHOOK_ID_HEADER = "Taxora-Webhook-Id";
1772
+ /** Default maximum age (seconds) of a signed request before it is rejected as a possible replay. */
1773
+ declare const DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
1774
+ /** The exact bytes Taxora sent. Never pass a parsed-and-re-serialised object. */
1775
+ type WebhookRawBody = string | Uint8Array | ArrayBuffer;
1776
+ /** Header value as frameworks hand it over (Express/Node may give an array for repeated headers). */
1777
+ type WebhookSignatureHeaderInput = string | readonly string[] | null | undefined;
1778
+ interface WebhookVerifyOptions {
1779
+ /**
1780
+ * Maximum allowed difference between now and the signature timestamp, in seconds. Default 300.
1781
+ * `0` disables the check — not recommended, it re-opens replay attacks.
1782
+ */
1783
+ tolerance?: number;
1784
+ /** Current time in Unix seconds. Only meant for tests. */
1785
+ now?: number;
1786
+ }
1787
+ type WebhookSignatureErrorReason = 'missing_secret' | 'missing_header' | 'malformed_header' | 'invalid_body' | 'timestamp_outside_tolerance' | 'no_matching_signature' | 'invalid_payload';
1788
+ declare class WebhookSignatureVerificationError extends TaxoraException {
1789
+ readonly reason: WebhookSignatureErrorReason;
1790
+ constructor(message: string, reason: WebhookSignatureErrorReason, context?: Record<string, unknown>);
1791
+ }
1792
+ interface ParsedWebhookSignatureHeader {
1793
+ timestamp: number;
1794
+ /** All `v1` signatures — two during a secret rotation on Taxora's side. */
1795
+ signatures: string[];
1796
+ }
1797
+ /** Parses `t=<unix>,v1=<hex>[,v1=<hex>…]`. Unknown schemes are ignored for forward compatibility. */
1798
+ declare function parseWebhookSignatureHeader(header: WebhookSignatureHeaderInput): ParsedWebhookSignatureHeader;
1799
+ /** hex(HMAC-SHA256(secret, `${timestamp}.${rawBody}`)) — the value Taxora puts into `v1=`. */
1800
+ declare function computeWebhookSignature(rawBody: WebhookRawBody, timestamp: number, secret: string): string;
1801
+ /**
1802
+ * Builds a valid `Taxora-Signature` header value for a payload — handy for unit-testing your webhook handler
1803
+ * without calling Taxora.
1804
+ */
1805
+ declare function generateWebhookSignatureHeader(rawBody: WebhookRawBody, secret: string | readonly string[], timestamp?: number): string;
1806
+ /**
1807
+ * Verifies a Taxora webhook request. Returns `true` or throws {@link WebhookSignatureVerificationError}.
1808
+ *
1809
+ * - `rawBody` must be the unmodified request body (e.g. `express.raw()`, `await request.text()`).
1810
+ * - `secret` may be a list — useful while you rotate the secret on your side.
1811
+ * - The comparison is constant-time; the timestamp must be within `tolerance` seconds (default 300).
1812
+ */
1813
+ declare function verifyWebhookSignature(rawBody: WebhookRawBody, header: WebhookSignatureHeaderInput, secret: string | readonly string[], options?: WebhookVerifyOptions): true;
1814
+ /**
1815
+ * Verifies the signature and returns the parsed, typed event. Throws {@link WebhookSignatureVerificationError}
1816
+ * on any problem — respond with HTTP 400 in that case.
1817
+ *
1818
+ * ```ts
1819
+ * app.post('/taxora-webhook', express.raw({ type: 'application/json' }), (req, res) => {
1820
+ * const event = constructWebhookEvent(req.body, req.header('Taxora-Signature'), process.env.TAXORA_WEBHOOK_SECRET!);
1821
+ * if (event.event === 'vat.validated') { ... }
1822
+ * res.sendStatus(200);
1823
+ * });
1824
+ * ```
1825
+ */
1826
+ declare function constructWebhookEvent<T extends TaxoraWebhookEvent = TaxoraWebhookEvent>(rawBody: WebhookRawBody, header: WebhookSignatureHeaderInput, secret: string | readonly string[], options?: WebhookVerifyOptions): T;
1827
+
1351
1828
  declare class AuthenticationException extends TaxoraException {
1352
1829
  readonly statusCode = 401;
1353
1830
  constructor(message: string, context?: Record<string, unknown>);
@@ -1420,4 +1897,4 @@ declare class AuthRetryHttpClient implements HttpClientInterface {
1420
1897
  private injectAuthHeader;
1421
1898
  }
1422
1899
 
1423
- export { ApiVersion, AuthEndpoint, AuthRetryHttpClient, AuthenticationException, CompanyAddress, CompanyEndpoint, type CompanyResource, ComplianceEnrollment, ComplianceEnrollmentPage, ComplianceEnrollmentStatus, type ComplianceEnterpriseSize, type ComplianceInvoiceLineInput, type ComplianceInvoiceTaxInput, ComplianceTaxReport, ComplianceTaxReportPage, type ComplianceTaxReportRequestState, ComplianceTaxReportState, ComplianceTransaction, type ComplianceTransactionFilters, ComplianceTransactionPage, type ComplianceTransactionRequestState, type ComplianceTransactionRequestType, ComplianceTransactionState, ComplianceTransactionType, type ComplianceTypeOperation, type CreateComplianceEnrollmentInput, type CreateComplianceTransactionInput, type EReportingAccessRequestInput, EReportingEndpoint, type EReportingInterval, Environment, Environment as EnvironmentType, FetchHttpClient, type HttpClientInterface, HttpException, ImportResult, InMemoryTokenStorage, Language, LoginIdentifier, ProviderDocument, ProviderDocumentLine, RetryPolicy, type RetryPolicyOptions, type RevenueCountryBreakdown, type RevenueCurrencyBreakdown, type RevenueStateBreakdown, RevenueStatistics, type RevenueStatisticsFilters, type RevenueTimeBucket, type RevenueTotals, type RevenueTypeBreakdown, ScoreBreakdown, SireneLookupResult, type SmartEnrichmentAddressQuality, type SmartEnrichmentConfidenceBucket, SmartEnrichmentEndpoint, type SmartEnrichmentExportOptions, type SmartEnrichmentHistoryInput, SmartEnrichmentHistoryPage, SmartEnrichmentHistoryRow, type SmartEnrichmentHistoryStats, type SmartEnrichmentInput, SmartEnrichmentJob, SmartEnrichmentMode, type SmartEnrichmentOutcomeBreakdown, type SmartEnrichmentProviderVerdict, SmartEnrichmentResource, type SmartEnrichmentSourceBreakdown, SmartEnrichmentStatistics, type SmartEnrichmentStatisticsInterval, type SmartEnrichmentStatisticsOptions, type SmartEnrichmentStatisticsRange, type SmartEnrichmentStatisticsTotals, SmartEnrichmentStatus, type SmartEnrichmentTimeBucket, type SmartEnrichmentUsage, type SmartEnrichmentUsageHistoryEntry, type SmartEnrichmentWaitOptions, TaxoraClient, TaxoraClientFactory, type TaxoraClientOptions, TaxoraException, Token, type TokenStorageInterface, type UpdateComplianceTransactionInput, ValidationException, VatCertificateExport, VatCollection, VatEndpoint, type VatRate, VatRates, VatResource, VatState, VatValidationAddressInput, describeApiError, describeComplianceEnrollmentStatus, describeComplianceTaxReportState, describeComplianceTransactionState, describeComplianceTransactionType, describeSmartEnrichmentMode, describeSmartEnrichmentStatus, describeVatState, getBaseUrl, getFailedVatStates, toComplianceEnrollmentStatus, toComplianceTaxReportState, toComplianceTransactionState, toComplianceTransactionType, toSmartEnrichmentMode, toSmartEnrichmentStatus };
1900
+ export { ApiVersion, AuthEndpoint, AuthRetryHttpClient, AuthenticationException, CompanyAddress, CompanyEndpoint, type CompanyResource, ComplianceDocumentType, ComplianceEnrollment, ComplianceEnrollmentPage, ComplianceEnrollmentStatus, type ComplianceEnterpriseSize, type ComplianceInvoiceLineInput, type ComplianceInvoiceTaxInput, type ComplianceLedgerStateChangedEvent, type ComplianceLedgerWebhookObject, type ComplianceRequestService, ComplianceService, ComplianceTaxReport, ComplianceTaxReportPage, type ComplianceTaxReportRequestState, ComplianceTaxReportState, ComplianceTransaction, type ComplianceTransactionBuyerInput, type ComplianceTransactionFilters, type ComplianceTransactionInvoiceLine, type ComplianceTransactionInvoiceLineTax, ComplianceTransactionPage, type ComplianceTransactionRequestState, type ComplianceTransactionRequestType, ComplianceTransactionState, type ComplianceTransactionStateChangedEvent, ComplianceTransactionType, type ComplianceTransactionWebhookObject, type ComplianceTypeOperation, type CreateComplianceEnrollmentInput, type CreateComplianceTransactionInput, type CreateNorwayEnrollmentInput, DEFAULT_WEBHOOK_TOLERANCE_SECONDS, type EReportingAccessRequestInput, EReportingEndpoint, type EReportingInterval, type EnrichmentCompletedEvent, type EnrichmentCompletedWebhookObject, type EnrichmentUpdatedEvent, type EnrichmentUpdatedWebhookObject, Environment, Environment as EnvironmentType, FetchHttpClient, type HttpClientInterface, HttpException, ImportResult, InMemoryTokenStorage, Language, LoginIdentifier, type NorwayEnrollmentInput, NorwegianOrgNumber, type ParsedWebhookSignatureHeader, PeppolLookupResult, PeppolLookupStatus, ProviderDocument, ProviderDocumentLine, RegistryCompany, RetryPolicy, type RetryPolicyOptions, type RevenueCountryBreakdown, type RevenueCurrencyBreakdown, type RevenueStateBreakdown, RevenueStatistics, type RevenueStatisticsFilters, type RevenueTimeBucket, type RevenueTotals, type RevenueTypeBreakdown, ScoreBreakdown, SireneLookupResult, type SmartEnrichmentAddressQuality, type SmartEnrichmentConfidenceBucket, SmartEnrichmentEndpoint, type SmartEnrichmentExportOptions, type SmartEnrichmentHistoryInput, SmartEnrichmentHistoryPage, SmartEnrichmentHistoryRow, type SmartEnrichmentHistoryStats, type SmartEnrichmentInput, SmartEnrichmentJob, SmartEnrichmentMode, type SmartEnrichmentOutcomeBreakdown, type SmartEnrichmentProviderVerdict, SmartEnrichmentResource, type SmartEnrichmentSourceBreakdown, SmartEnrichmentStatistics, type SmartEnrichmentStatisticsInterval, type SmartEnrichmentStatisticsOptions, type SmartEnrichmentStatisticsRange, type SmartEnrichmentStatisticsTotals, SmartEnrichmentStatus, type SmartEnrichmentTimeBucket, type SmartEnrichmentUsage, type SmartEnrichmentUsageHistoryEntry, type SmartEnrichmentWaitOptions, TaxoraClient, TaxoraClientFactory, type TaxoraClientOptions, TaxoraException, type TaxoraWebhookEvent, type TestWebhookObject, Token, type TokenStorageInterface, type UpdateComplianceTransactionInput, ValidationException, VatCertificateExport, VatCollection, VatEndpoint, type VatRate, VatRates, VatResource, VatState, type VatStateChangedEvent, type VatValidatedEvent, VatValidationAddressInput, type VatWebhookObject, WEBHOOK_ID_HEADER, WEBHOOK_SIGNATURE_HEADER, type WebhookEventEnvelope, type WebhookEventType, type WebhookRawBody, type WebhookSignatureErrorReason, type WebhookSignatureHeaderInput, WebhookSignatureVerificationError, type WebhookTestEvent, type WebhookVerifyOptions, computeWebhookSignature, constructWebhookEvent, describeApiError, describeComplianceDocumentType, describeComplianceEnrollmentStatus, describeComplianceService, describeComplianceTaxReportState, describeComplianceTransactionState, describeComplianceTransactionType, describePeppolLookupStatus, describeSmartEnrichmentMode, describeSmartEnrichmentStatus, describeVatState, generateWebhookSignatureHeader, getBaseUrl, getFailedVatStates, parseWebhookSignatureHeader, toComplianceDocumentType, toComplianceEnrollmentStatus, toComplianceService, toComplianceTaxReportState, toComplianceTransactionState, toComplianceTransactionType, toPeppolLookupStatus, toSmartEnrichmentMode, toSmartEnrichmentStatus, verifyWebhookSignature };