@timbrix/sdk 1.3.0 → 2.0.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.mts CHANGED
@@ -550,6 +550,33 @@ interface ListInvoicesResponse {
550
550
  limit: number;
551
551
  totalPages: number;
552
552
  }
553
+ interface CfdiUsage {
554
+ plan: "starter" | "pro" | "business" | "enterprise";
555
+ /** null = unlimited (enterprise plan) */
556
+ cfdiIncluded: number | null;
557
+ cfdiUsedThisMonth: number;
558
+ /** null = unlimited (enterprise plan) */
559
+ cfdiRemaining: number | null;
560
+ periodResetsAt: string;
561
+ }
562
+ interface CancelInvoiceInput {
563
+ /** 01 = con relación (requiere folioSustitucion), 02 = sin relación, 03 = no se llevó a cabo la operación, 04 = operación nominativa relacionada en factura global */
564
+ motivo: "01" | "02" | "03" | "04";
565
+ folioSustitucion?: string;
566
+ }
567
+ interface InvoiceCancellation {
568
+ id: string;
569
+ invoiceId: string;
570
+ motivo: string;
571
+ folioSustitucion?: string | null;
572
+ requiresApproval: boolean;
573
+ respondBy?: string | null;
574
+ cancellationStatus: "pendiente" | "aceptada" | "rechazada";
575
+ requestedBy?: string | null;
576
+ resolvedBy?: string | null;
577
+ resolvedAt?: string | null;
578
+ createdAt: string;
579
+ }
553
580
  interface TimbrixError {
554
581
  statusCode: number;
555
582
  message: string | string[];
@@ -606,25 +633,28 @@ declare class CustomersResource {
606
633
  private http;
607
634
  constructor(http: KyInstance);
608
635
  /**
609
- * List all customers for an organization
636
+ * List all customers. Works with either an API key (organization
637
+ * resolved from the key — omit `organizationId`) or a Supabase bearer
638
+ * session (pass `organizationId` explicitly; sent as the
639
+ * `X-Organization-Id` header).
610
640
  */
611
- list(organizationId: string): Promise<Customer[]>;
641
+ list(organizationId?: string): Promise<Customer[]>;
612
642
  /**
613
- * Get a customer by ID
643
+ * Get a customer by ID. Same `organizationId` rules as `list`.
614
644
  */
615
- get(organizationId: string, customerId: string): Promise<Customer>;
645
+ get(customerId: string, organizationId?: string): Promise<Customer>;
616
646
  /**
617
- * Create a new customer
647
+ * Create a new customer. Same `organizationId` rules as `list`.
618
648
  */
619
- create(organizationId: string, data: CreateCustomerInput): Promise<Customer>;
649
+ create(data: CreateCustomerInput, organizationId?: string): Promise<Customer>;
620
650
  /**
621
- * Update a customer
651
+ * Update a customer. Same `organizationId` rules as `list`.
622
652
  */
623
- update(organizationId: string, customerId: string, data: UpdateCustomerInput): Promise<Customer>;
653
+ update(customerId: string, data: UpdateCustomerInput, organizationId?: string): Promise<Customer>;
624
654
  /**
625
- * Delete a customer
655
+ * Delete a customer. Same `organizationId` rules as `list`.
626
656
  */
627
- delete(organizationId: string, customerId: string): Promise<void>;
657
+ delete(customerId: string, organizationId?: string): Promise<void>;
628
658
  }
629
659
 
630
660
  declare class InvoicesResource {
@@ -632,18 +662,28 @@ declare class InvoicesResource {
632
662
  constructor(http: KyInstance);
633
663
  /**
634
664
  * Create and stamp (timbrar) a CFDI 4.0 invoice via the configured PAC.
635
- * Works with either a Supabase bearer session (internal dashboard, the
636
- * user must be a member of `organizationId`) or an API key (external
637
- * integrations, requires the `write:invoices` scope — the key must
638
- * belong to `organizationId`).
665
+ * Works with either a Supabase bearer session (pass `organizationId`,
666
+ * the user must be a member of it) or an API key (external
667
+ * integrations, requires the `write:invoices` scope)when the client
668
+ * is authenticated with an API key, `organizationId` can be omitted and
669
+ * is resolved from the key itself. When provided, sent as the
670
+ * `X-Organization-Id` header.
639
671
  */
640
- create(organizationId: string, data: CreateInvoiceInput): Promise<Invoice>;
672
+ create(data: CreateInvoiceInput, organizationId?: string): Promise<Invoice>;
641
673
  /**
642
- * List invoices for an organization, newest first. Works with either a
643
- * Supabase bearer session or an API key (requires the `read:invoices`
644
- * scope), same rules as `create`.
674
+ * Generate a PDF preview of a CFDI 4.0 invoice without stamping
675
+ * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
676
+ * is consumed. Accepts the same body shape as `create`. Same auth rules
677
+ * as `create` — `organizationId` is optional when authenticated with an
678
+ * API key. When provided, sent as the `X-Organization-Id` header.
679
+ */
680
+ previewPdf(data: CreateInvoiceInput, organizationId?: string): Promise<Blob>;
681
+ /**
682
+ * List invoices for an organization, newest first. Same auth rules as
683
+ * `create` — `organizationId` is optional when authenticated with an
684
+ * API key. When provided, sent as the `X-Organization-Id` header.
645
685
  */
646
- list(organizationId: string, params?: ListInvoicesParams): Promise<ListInvoicesResponse>;
686
+ list(params?: ListInvoicesParams, organizationId?: string): Promise<ListInvoicesResponse>;
647
687
  /**
648
688
  * Get a single CFDI 4.0 invoice by its folio fiscal (UUID). Works with
649
689
  * either a Supabase bearer session or an API key (requires the
@@ -662,6 +702,23 @@ declare class InvoicesResource {
662
702
  * scope).
663
703
  */
664
704
  getPdf(uuid: string): Promise<Blob>;
705
+ /**
706
+ * Cancel a stamped CFDI 4.0 invoice per SAT rules. Works with either a
707
+ * Supabase bearer session or an API key (requires the `write:invoices`
708
+ * scope). Returns immediately with `cancellationStatus: "pendiente"`
709
+ * when the SAT requires receptor approval — Timbrix cannot confirm that
710
+ * approval in real time.
711
+ */
712
+ cancel(uuid: string, data: CancelInvoiceInput): Promise<InvoiceCancellation>;
713
+ /**
714
+ * Get how many CFDI the organization has stamped this calendar month
715
+ * (Mexico City time) against its plan's included quota. `cfdiIncluded`
716
+ * and `cfdiRemaining` are `null` for the enterprise plan (unlimited).
717
+ * `organizationId` is optional when authenticated with an API key
718
+ * (resolved from the key). When provided, sent as the `X-Organization-Id`
719
+ * header.
720
+ */
721
+ usage(organizationId?: string): Promise<CfdiUsage>;
665
722
  }
666
723
 
667
724
  declare class OAuthResource {
@@ -762,25 +819,28 @@ declare class ProductsResource {
762
819
  private http;
763
820
  constructor(http: KyInstance);
764
821
  /**
765
- * List products for an organization, with optional filters
822
+ * List products, with optional filters. Works with either an API key
823
+ * (organization resolved from the key — omit `organizationId`) or a
824
+ * Supabase bearer session (pass `organizationId` explicitly; sent as the
825
+ * `X-Organization-Id` header).
766
826
  */
767
- list(organizationId: string, filters?: ListProductsFilters): Promise<Product[]>;
827
+ list(filters?: ListProductsFilters, organizationId?: string): Promise<Product[]>;
768
828
  /**
769
- * Get a product by ID
829
+ * Get a product by ID. Same `organizationId` rules as `list`.
770
830
  */
771
- get(organizationId: string, productId: string): Promise<Product>;
831
+ get(productId: string, organizationId?: string): Promise<Product>;
772
832
  /**
773
- * Create a new product or service
833
+ * Create a new product or service. Same `organizationId` rules as `list`.
774
834
  */
775
- create(organizationId: string, data: CreateProductInput): Promise<Product>;
835
+ create(data: CreateProductInput, organizationId?: string): Promise<Product>;
776
836
  /**
777
- * Update a product
837
+ * Update a product. Same `organizationId` rules as `list`.
778
838
  */
779
- update(organizationId: string, productId: string, data: UpdateProductInput): Promise<Product>;
839
+ update(productId: string, data: UpdateProductInput, organizationId?: string): Promise<Product>;
780
840
  /**
781
- * Delete a product
841
+ * Delete a product. Same `organizationId` rules as `list`.
782
842
  */
783
- delete(organizationId: string, productId: string): Promise<void>;
843
+ delete(productId: string, organizationId?: string): Promise<void>;
784
844
  /**
785
845
  * Bulk import products/services from a CSV file (multipart/form-data,
786
846
  * field name "file"). Works in both Node (18+) and browser environments,
@@ -792,9 +852,9 @@ declare class ProductsResource {
792
852
  * even if other rows fail, and every failure is reported with its row
793
853
  * number and reason.
794
854
  *
795
- * Calls POST /organizations/:organizationId/products/import
855
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
796
856
  */
797
- importCsv(organizationId: string, file: Blob | File, filename?: string): Promise<ImportProductsCsvResult>;
857
+ importCsv(file: Blob | File, filename?: string, organizationId?: string): Promise<ImportProductsCsvResult>;
798
858
  }
799
859
 
800
860
  declare class SatResource {
@@ -919,4 +979,4 @@ declare class ApiKeyAuth implements AuthStrategy {
919
979
  applyAuth(options: Options): Options;
920
980
  }
921
981
 
922
- export { type ApiKey, ApiKeyAuth, type ApiKeyScope, type ApiKeyStats, type ApiKeyValidateResponse, ApiKeysResource, type AuthMode, AuthResource, type AuthStrategy, BearerAuth, type ClaveProdServ, type ClaveUnidad, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateCustomerInput, type CreateInvoiceInput, type CreateOAuthAppInput, type CreateOrganizationInput, type CreateProductInput, type CreateWebhookInput, type Customer, type CustomerAddress, CustomersResource, type ExchangeCodeInput, type GenerateTokenInput, type ImportProductsCsvResult, type ImportProductsCsvRowError, type InviteMemberInput, type Invoice, type InvoiceCustomerInput, type InvoiceItemInput, type InvoiceListItem, type InvoiceTaxInput, InvoicesResource, type LegalAddress, type ListInvoicesParams, type ListInvoicesResponse, type ListProductsFilters, type ListRegimenesParams, type ListUsosCfdiParams, type LoginInput, type LoginResponse, type OAuthApp, type OAuthAppWithSecret, OAuthResource, type OAuthScope, type OAuthToken, type Organization, type OrganizationDetails, type OrganizationInvite, type OrganizationMember, type OrganizationRole, OrganizationsResource, type Product, type ProductTax, ProductsResource, type RefreshTokenInput, type RegimenFiscal, SatResource, type SearchClavesParams, type SearchClavesProdServResult, type SearchClavesUnidadResult, Timbrix, type TimbrixConfig, type TimbrixError, type TimbrixUser, type TipoPersona, type TokenResponse, type UpdateApiKeyInput, type UpdateCustomerInput, type UpdateLegalDataInput, type UpdateMemberRoleInput, type UpdateOAuthAppInput, type UpdateOrganizationInput, type UpdateProductInput, type UpdateWebhookInput, UsersResource, type UsoCfdi, type ValidateCertificateResponse, type Webhook, type WebhookDelivery, type WebhookEvent, WebhooksResource };
982
+ export { type ApiKey, ApiKeyAuth, type ApiKeyScope, type ApiKeyStats, type ApiKeyValidateResponse, ApiKeysResource, type AuthMode, AuthResource, type AuthStrategy, BearerAuth, type CancelInvoiceInput, type CfdiUsage, type ClaveProdServ, type ClaveUnidad, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateCustomerInput, type CreateInvoiceInput, type CreateOAuthAppInput, type CreateOrganizationInput, type CreateProductInput, type CreateWebhookInput, type Customer, type CustomerAddress, CustomersResource, type ExchangeCodeInput, type GenerateTokenInput, type ImportProductsCsvResult, type ImportProductsCsvRowError, type InviteMemberInput, type Invoice, type InvoiceCancellation, type InvoiceCustomerInput, type InvoiceItemInput, type InvoiceListItem, type InvoiceTaxInput, InvoicesResource, type LegalAddress, type ListInvoicesParams, type ListInvoicesResponse, type ListProductsFilters, type ListRegimenesParams, type ListUsosCfdiParams, type LoginInput, type LoginResponse, type OAuthApp, type OAuthAppWithSecret, OAuthResource, type OAuthScope, type OAuthToken, type Organization, type OrganizationDetails, type OrganizationInvite, type OrganizationMember, type OrganizationRole, OrganizationsResource, type Product, type ProductTax, ProductsResource, type RefreshTokenInput, type RegimenFiscal, SatResource, type SearchClavesParams, type SearchClavesProdServResult, type SearchClavesUnidadResult, Timbrix, type TimbrixConfig, type TimbrixError, type TimbrixUser, type TipoPersona, type TokenResponse, type UpdateApiKeyInput, type UpdateCustomerInput, type UpdateLegalDataInput, type UpdateMemberRoleInput, type UpdateOAuthAppInput, type UpdateOrganizationInput, type UpdateProductInput, type UpdateWebhookInput, UsersResource, type UsoCfdi, type ValidateCertificateResponse, type Webhook, type WebhookDelivery, type WebhookEvent, WebhooksResource };
package/dist/index.d.ts CHANGED
@@ -550,6 +550,33 @@ interface ListInvoicesResponse {
550
550
  limit: number;
551
551
  totalPages: number;
552
552
  }
553
+ interface CfdiUsage {
554
+ plan: "starter" | "pro" | "business" | "enterprise";
555
+ /** null = unlimited (enterprise plan) */
556
+ cfdiIncluded: number | null;
557
+ cfdiUsedThisMonth: number;
558
+ /** null = unlimited (enterprise plan) */
559
+ cfdiRemaining: number | null;
560
+ periodResetsAt: string;
561
+ }
562
+ interface CancelInvoiceInput {
563
+ /** 01 = con relación (requiere folioSustitucion), 02 = sin relación, 03 = no se llevó a cabo la operación, 04 = operación nominativa relacionada en factura global */
564
+ motivo: "01" | "02" | "03" | "04";
565
+ folioSustitucion?: string;
566
+ }
567
+ interface InvoiceCancellation {
568
+ id: string;
569
+ invoiceId: string;
570
+ motivo: string;
571
+ folioSustitucion?: string | null;
572
+ requiresApproval: boolean;
573
+ respondBy?: string | null;
574
+ cancellationStatus: "pendiente" | "aceptada" | "rechazada";
575
+ requestedBy?: string | null;
576
+ resolvedBy?: string | null;
577
+ resolvedAt?: string | null;
578
+ createdAt: string;
579
+ }
553
580
  interface TimbrixError {
554
581
  statusCode: number;
555
582
  message: string | string[];
@@ -606,25 +633,28 @@ declare class CustomersResource {
606
633
  private http;
607
634
  constructor(http: KyInstance);
608
635
  /**
609
- * List all customers for an organization
636
+ * List all customers. Works with either an API key (organization
637
+ * resolved from the key — omit `organizationId`) or a Supabase bearer
638
+ * session (pass `organizationId` explicitly; sent as the
639
+ * `X-Organization-Id` header).
610
640
  */
611
- list(organizationId: string): Promise<Customer[]>;
641
+ list(organizationId?: string): Promise<Customer[]>;
612
642
  /**
613
- * Get a customer by ID
643
+ * Get a customer by ID. Same `organizationId` rules as `list`.
614
644
  */
615
- get(organizationId: string, customerId: string): Promise<Customer>;
645
+ get(customerId: string, organizationId?: string): Promise<Customer>;
616
646
  /**
617
- * Create a new customer
647
+ * Create a new customer. Same `organizationId` rules as `list`.
618
648
  */
619
- create(organizationId: string, data: CreateCustomerInput): Promise<Customer>;
649
+ create(data: CreateCustomerInput, organizationId?: string): Promise<Customer>;
620
650
  /**
621
- * Update a customer
651
+ * Update a customer. Same `organizationId` rules as `list`.
622
652
  */
623
- update(organizationId: string, customerId: string, data: UpdateCustomerInput): Promise<Customer>;
653
+ update(customerId: string, data: UpdateCustomerInput, organizationId?: string): Promise<Customer>;
624
654
  /**
625
- * Delete a customer
655
+ * Delete a customer. Same `organizationId` rules as `list`.
626
656
  */
627
- delete(organizationId: string, customerId: string): Promise<void>;
657
+ delete(customerId: string, organizationId?: string): Promise<void>;
628
658
  }
629
659
 
630
660
  declare class InvoicesResource {
@@ -632,18 +662,28 @@ declare class InvoicesResource {
632
662
  constructor(http: KyInstance);
633
663
  /**
634
664
  * Create and stamp (timbrar) a CFDI 4.0 invoice via the configured PAC.
635
- * Works with either a Supabase bearer session (internal dashboard, the
636
- * user must be a member of `organizationId`) or an API key (external
637
- * integrations, requires the `write:invoices` scope — the key must
638
- * belong to `organizationId`).
665
+ * Works with either a Supabase bearer session (pass `organizationId`,
666
+ * the user must be a member of it) or an API key (external
667
+ * integrations, requires the `write:invoices` scope)when the client
668
+ * is authenticated with an API key, `organizationId` can be omitted and
669
+ * is resolved from the key itself. When provided, sent as the
670
+ * `X-Organization-Id` header.
639
671
  */
640
- create(organizationId: string, data: CreateInvoiceInput): Promise<Invoice>;
672
+ create(data: CreateInvoiceInput, organizationId?: string): Promise<Invoice>;
641
673
  /**
642
- * List invoices for an organization, newest first. Works with either a
643
- * Supabase bearer session or an API key (requires the `read:invoices`
644
- * scope), same rules as `create`.
674
+ * Generate a PDF preview of a CFDI 4.0 invoice without stamping
675
+ * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
676
+ * is consumed. Accepts the same body shape as `create`. Same auth rules
677
+ * as `create` — `organizationId` is optional when authenticated with an
678
+ * API key. When provided, sent as the `X-Organization-Id` header.
679
+ */
680
+ previewPdf(data: CreateInvoiceInput, organizationId?: string): Promise<Blob>;
681
+ /**
682
+ * List invoices for an organization, newest first. Same auth rules as
683
+ * `create` — `organizationId` is optional when authenticated with an
684
+ * API key. When provided, sent as the `X-Organization-Id` header.
645
685
  */
646
- list(organizationId: string, params?: ListInvoicesParams): Promise<ListInvoicesResponse>;
686
+ list(params?: ListInvoicesParams, organizationId?: string): Promise<ListInvoicesResponse>;
647
687
  /**
648
688
  * Get a single CFDI 4.0 invoice by its folio fiscal (UUID). Works with
649
689
  * either a Supabase bearer session or an API key (requires the
@@ -662,6 +702,23 @@ declare class InvoicesResource {
662
702
  * scope).
663
703
  */
664
704
  getPdf(uuid: string): Promise<Blob>;
705
+ /**
706
+ * Cancel a stamped CFDI 4.0 invoice per SAT rules. Works with either a
707
+ * Supabase bearer session or an API key (requires the `write:invoices`
708
+ * scope). Returns immediately with `cancellationStatus: "pendiente"`
709
+ * when the SAT requires receptor approval — Timbrix cannot confirm that
710
+ * approval in real time.
711
+ */
712
+ cancel(uuid: string, data: CancelInvoiceInput): Promise<InvoiceCancellation>;
713
+ /**
714
+ * Get how many CFDI the organization has stamped this calendar month
715
+ * (Mexico City time) against its plan's included quota. `cfdiIncluded`
716
+ * and `cfdiRemaining` are `null` for the enterprise plan (unlimited).
717
+ * `organizationId` is optional when authenticated with an API key
718
+ * (resolved from the key). When provided, sent as the `X-Organization-Id`
719
+ * header.
720
+ */
721
+ usage(organizationId?: string): Promise<CfdiUsage>;
665
722
  }
666
723
 
667
724
  declare class OAuthResource {
@@ -762,25 +819,28 @@ declare class ProductsResource {
762
819
  private http;
763
820
  constructor(http: KyInstance);
764
821
  /**
765
- * List products for an organization, with optional filters
822
+ * List products, with optional filters. Works with either an API key
823
+ * (organization resolved from the key — omit `organizationId`) or a
824
+ * Supabase bearer session (pass `organizationId` explicitly; sent as the
825
+ * `X-Organization-Id` header).
766
826
  */
767
- list(organizationId: string, filters?: ListProductsFilters): Promise<Product[]>;
827
+ list(filters?: ListProductsFilters, organizationId?: string): Promise<Product[]>;
768
828
  /**
769
- * Get a product by ID
829
+ * Get a product by ID. Same `organizationId` rules as `list`.
770
830
  */
771
- get(organizationId: string, productId: string): Promise<Product>;
831
+ get(productId: string, organizationId?: string): Promise<Product>;
772
832
  /**
773
- * Create a new product or service
833
+ * Create a new product or service. Same `organizationId` rules as `list`.
774
834
  */
775
- create(organizationId: string, data: CreateProductInput): Promise<Product>;
835
+ create(data: CreateProductInput, organizationId?: string): Promise<Product>;
776
836
  /**
777
- * Update a product
837
+ * Update a product. Same `organizationId` rules as `list`.
778
838
  */
779
- update(organizationId: string, productId: string, data: UpdateProductInput): Promise<Product>;
839
+ update(productId: string, data: UpdateProductInput, organizationId?: string): Promise<Product>;
780
840
  /**
781
- * Delete a product
841
+ * Delete a product. Same `organizationId` rules as `list`.
782
842
  */
783
- delete(organizationId: string, productId: string): Promise<void>;
843
+ delete(productId: string, organizationId?: string): Promise<void>;
784
844
  /**
785
845
  * Bulk import products/services from a CSV file (multipart/form-data,
786
846
  * field name "file"). Works in both Node (18+) and browser environments,
@@ -792,9 +852,9 @@ declare class ProductsResource {
792
852
  * even if other rows fail, and every failure is reported with its row
793
853
  * number and reason.
794
854
  *
795
- * Calls POST /organizations/:organizationId/products/import
855
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
796
856
  */
797
- importCsv(organizationId: string, file: Blob | File, filename?: string): Promise<ImportProductsCsvResult>;
857
+ importCsv(file: Blob | File, filename?: string, organizationId?: string): Promise<ImportProductsCsvResult>;
798
858
  }
799
859
 
800
860
  declare class SatResource {
@@ -919,4 +979,4 @@ declare class ApiKeyAuth implements AuthStrategy {
919
979
  applyAuth(options: Options): Options;
920
980
  }
921
981
 
922
- export { type ApiKey, ApiKeyAuth, type ApiKeyScope, type ApiKeyStats, type ApiKeyValidateResponse, ApiKeysResource, type AuthMode, AuthResource, type AuthStrategy, BearerAuth, type ClaveProdServ, type ClaveUnidad, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateCustomerInput, type CreateInvoiceInput, type CreateOAuthAppInput, type CreateOrganizationInput, type CreateProductInput, type CreateWebhookInput, type Customer, type CustomerAddress, CustomersResource, type ExchangeCodeInput, type GenerateTokenInput, type ImportProductsCsvResult, type ImportProductsCsvRowError, type InviteMemberInput, type Invoice, type InvoiceCustomerInput, type InvoiceItemInput, type InvoiceListItem, type InvoiceTaxInput, InvoicesResource, type LegalAddress, type ListInvoicesParams, type ListInvoicesResponse, type ListProductsFilters, type ListRegimenesParams, type ListUsosCfdiParams, type LoginInput, type LoginResponse, type OAuthApp, type OAuthAppWithSecret, OAuthResource, type OAuthScope, type OAuthToken, type Organization, type OrganizationDetails, type OrganizationInvite, type OrganizationMember, type OrganizationRole, OrganizationsResource, type Product, type ProductTax, ProductsResource, type RefreshTokenInput, type RegimenFiscal, SatResource, type SearchClavesParams, type SearchClavesProdServResult, type SearchClavesUnidadResult, Timbrix, type TimbrixConfig, type TimbrixError, type TimbrixUser, type TipoPersona, type TokenResponse, type UpdateApiKeyInput, type UpdateCustomerInput, type UpdateLegalDataInput, type UpdateMemberRoleInput, type UpdateOAuthAppInput, type UpdateOrganizationInput, type UpdateProductInput, type UpdateWebhookInput, UsersResource, type UsoCfdi, type ValidateCertificateResponse, type Webhook, type WebhookDelivery, type WebhookEvent, WebhooksResource };
982
+ export { type ApiKey, ApiKeyAuth, type ApiKeyScope, type ApiKeyStats, type ApiKeyValidateResponse, ApiKeysResource, type AuthMode, AuthResource, type AuthStrategy, BearerAuth, type CancelInvoiceInput, type CfdiUsage, type ClaveProdServ, type ClaveUnidad, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateCustomerInput, type CreateInvoiceInput, type CreateOAuthAppInput, type CreateOrganizationInput, type CreateProductInput, type CreateWebhookInput, type Customer, type CustomerAddress, CustomersResource, type ExchangeCodeInput, type GenerateTokenInput, type ImportProductsCsvResult, type ImportProductsCsvRowError, type InviteMemberInput, type Invoice, type InvoiceCancellation, type InvoiceCustomerInput, type InvoiceItemInput, type InvoiceListItem, type InvoiceTaxInput, InvoicesResource, type LegalAddress, type ListInvoicesParams, type ListInvoicesResponse, type ListProductsFilters, type ListRegimenesParams, type ListUsosCfdiParams, type LoginInput, type LoginResponse, type OAuthApp, type OAuthAppWithSecret, OAuthResource, type OAuthScope, type OAuthToken, type Organization, type OrganizationDetails, type OrganizationInvite, type OrganizationMember, type OrganizationRole, OrganizationsResource, type Product, type ProductTax, ProductsResource, type RefreshTokenInput, type RegimenFiscal, SatResource, type SearchClavesParams, type SearchClavesProdServResult, type SearchClavesUnidadResult, Timbrix, type TimbrixConfig, type TimbrixError, type TimbrixUser, type TipoPersona, type TokenResponse, type UpdateApiKeyInput, type UpdateCustomerInput, type UpdateLegalDataInput, type UpdateMemberRoleInput, type UpdateOAuthAppInput, type UpdateOrganizationInput, type UpdateProductInput, type UpdateWebhookInput, UsersResource, type UsoCfdi, type ValidateCertificateResponse, type Webhook, type WebhookDelivery, type WebhookEvent, WebhooksResource };
package/dist/index.js CHANGED
@@ -172,38 +172,49 @@ var CustomersResource = class {
172
172
  }
173
173
  http;
174
174
  /**
175
- * List all customers for an organization
175
+ * List all customers. Works with either an API key (organization
176
+ * resolved from the key — omit `organizationId`) or a Supabase bearer
177
+ * session (pass `organizationId` explicitly; sent as the
178
+ * `X-Organization-Id` header).
176
179
  */
177
180
  async list(organizationId) {
178
- return this.http.get(`organizations/${organizationId}/customers`).json();
181
+ return this.http.get("customers", {
182
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
183
+ }).json();
179
184
  }
180
185
  /**
181
- * Get a customer by ID
186
+ * Get a customer by ID. Same `organizationId` rules as `list`.
182
187
  */
183
- async get(organizationId, customerId) {
184
- return this.http.get(`organizations/${organizationId}/customers/${customerId}`).json();
188
+ async get(customerId, organizationId) {
189
+ return this.http.get(`customers/${customerId}`, {
190
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
191
+ }).json();
185
192
  }
186
193
  /**
187
- * Create a new customer
194
+ * Create a new customer. Same `organizationId` rules as `list`.
188
195
  */
189
- async create(organizationId, data) {
190
- return this.http.post(`organizations/${organizationId}/customers`, { json: data }).json();
196
+ async create(data, organizationId) {
197
+ return this.http.post("customers", {
198
+ json: data,
199
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
200
+ }).json();
191
201
  }
192
202
  /**
193
- * Update a customer
203
+ * Update a customer. Same `organizationId` rules as `list`.
194
204
  */
195
- async update(organizationId, customerId, data) {
196
- return this.http.put(`organizations/${organizationId}/customers/${customerId}`, {
197
- json: data
205
+ async update(customerId, data, organizationId) {
206
+ return this.http.put(`customers/${customerId}`, {
207
+ json: data,
208
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
198
209
  }).json();
199
210
  }
200
211
  /**
201
- * Delete a customer
212
+ * Delete a customer. Same `organizationId` rules as `list`.
202
213
  */
203
- async delete(organizationId, customerId) {
204
- await this.http.delete(
205
- `organizations/${organizationId}/customers/${customerId}`
206
- );
214
+ async delete(customerId, organizationId) {
215
+ await this.http.delete(`customers/${customerId}`, {
216
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
217
+ });
207
218
  }
208
219
  };
209
220
 
@@ -215,27 +226,46 @@ var InvoicesResource = class {
215
226
  http;
216
227
  /**
217
228
  * Create and stamp (timbrar) a CFDI 4.0 invoice via the configured PAC.
218
- * Works with either a Supabase bearer session (internal dashboard, the
219
- * user must be a member of `organizationId`) or an API key (external
220
- * integrations, requires the `write:invoices` scope — the key must
221
- * belong to `organizationId`).
229
+ * Works with either a Supabase bearer session (pass `organizationId`,
230
+ * the user must be a member of it) or an API key (external
231
+ * integrations, requires the `write:invoices` scope)when the client
232
+ * is authenticated with an API key, `organizationId` can be omitted and
233
+ * is resolved from the key itself. When provided, sent as the
234
+ * `X-Organization-Id` header.
235
+ */
236
+ async create(data, organizationId) {
237
+ return this.http.post("invoices", {
238
+ json: data,
239
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
240
+ }).json();
241
+ }
242
+ /**
243
+ * Generate a PDF preview of a CFDI 4.0 invoice without stamping
244
+ * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
245
+ * is consumed. Accepts the same body shape as `create`. Same auth rules
246
+ * as `create` — `organizationId` is optional when authenticated with an
247
+ * API key. When provided, sent as the `X-Organization-Id` header.
222
248
  */
223
- async create(organizationId, data) {
224
- return this.http.post(`organizations/${organizationId}/invoices`, { json: data }).json();
249
+ async previewPdf(data, organizationId) {
250
+ return this.http.post("invoices/preview/pdf", {
251
+ json: data,
252
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
253
+ }).blob();
225
254
  }
226
255
  /**
227
- * List invoices for an organization, newest first. Works with either a
228
- * Supabase bearer session or an API key (requires the `read:invoices`
229
- * scope), same rules as `create`.
256
+ * List invoices for an organization, newest first. Same auth rules as
257
+ * `create` `organizationId` is optional when authenticated with an
258
+ * API key. When provided, sent as the `X-Organization-Id` header.
230
259
  */
231
- async list(organizationId, params) {
260
+ async list(params, organizationId) {
232
261
  const searchParams = {};
233
262
  if (params?.page !== void 0) searchParams.page = String(params.page);
234
263
  if (params?.limit !== void 0) searchParams.limit = String(params.limit);
235
264
  if (params?.type !== void 0) searchParams.type = params.type;
236
265
  if (params?.status !== void 0) searchParams.status = params.status;
237
- return this.http.get(`organizations/${organizationId}/invoices`, {
238
- searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0
266
+ return this.http.get("invoices", {
267
+ searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0,
268
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
239
269
  }).json();
240
270
  }
241
271
  /**
@@ -262,6 +292,29 @@ var InvoicesResource = class {
262
292
  async getPdf(uuid) {
263
293
  return this.http.get(`invoices/${uuid}/pdf`).blob();
264
294
  }
295
+ /**
296
+ * Cancel a stamped CFDI 4.0 invoice per SAT rules. Works with either a
297
+ * Supabase bearer session or an API key (requires the `write:invoices`
298
+ * scope). Returns immediately with `cancellationStatus: "pendiente"`
299
+ * when the SAT requires receptor approval — Timbrix cannot confirm that
300
+ * approval in real time.
301
+ */
302
+ async cancel(uuid, data) {
303
+ return this.http.post(`invoices/${uuid}/cancel`, { json: data }).json();
304
+ }
305
+ /**
306
+ * Get how many CFDI the organization has stamped this calendar month
307
+ * (Mexico City time) against its plan's included quota. `cfdiIncluded`
308
+ * and `cfdiRemaining` are `null` for the enterprise plan (unlimited).
309
+ * `organizationId` is optional when authenticated with an API key
310
+ * (resolved from the key). When provided, sent as the `X-Organization-Id`
311
+ * header.
312
+ */
313
+ async usage(organizationId) {
314
+ return this.http.get("usage", {
315
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
316
+ }).json();
317
+ }
265
318
  };
266
319
 
267
320
  // src/resources/oauth.ts
@@ -434,45 +487,55 @@ var ProductsResource = class {
434
487
  }
435
488
  http;
436
489
  /**
437
- * List products for an organization, with optional filters
490
+ * List products, with optional filters. Works with either an API key
491
+ * (organization resolved from the key — omit `organizationId`) or a
492
+ * Supabase bearer session (pass `organizationId` explicitly; sent as the
493
+ * `X-Organization-Id` header).
438
494
  */
439
- async list(organizationId, filters) {
495
+ async list(filters, organizationId) {
440
496
  const searchParams = {};
441
497
  if (filters?.description) searchParams.description = filters.description;
442
498
  if (filters?.sku) searchParams.sku = filters.sku;
443
499
  if (filters?.productKey !== void 0)
444
500
  searchParams.productKey = String(filters.productKey);
445
- return this.http.get(`organizations/${organizationId}/products`, {
446
- searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0
501
+ return this.http.get("products", {
502
+ searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0,
503
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
447
504
  }).json();
448
505
  }
449
506
  /**
450
- * Get a product by ID
507
+ * Get a product by ID. Same `organizationId` rules as `list`.
451
508
  */
452
- async get(organizationId, productId) {
453
- return this.http.get(`organizations/${organizationId}/products/${productId}`).json();
509
+ async get(productId, organizationId) {
510
+ return this.http.get(`products/${productId}`, {
511
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
512
+ }).json();
454
513
  }
455
514
  /**
456
- * Create a new product or service
515
+ * Create a new product or service. Same `organizationId` rules as `list`.
457
516
  */
458
- async create(organizationId, data) {
459
- return this.http.post(`organizations/${organizationId}/products`, { json: data }).json();
517
+ async create(data, organizationId) {
518
+ return this.http.post("products", {
519
+ json: data,
520
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
521
+ }).json();
460
522
  }
461
523
  /**
462
- * Update a product
524
+ * Update a product. Same `organizationId` rules as `list`.
463
525
  */
464
- async update(organizationId, productId, data) {
465
- return this.http.put(`organizations/${organizationId}/products/${productId}`, {
466
- json: data
526
+ async update(productId, data, organizationId) {
527
+ return this.http.put(`products/${productId}`, {
528
+ json: data,
529
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
467
530
  }).json();
468
531
  }
469
532
  /**
470
- * Delete a product
533
+ * Delete a product. Same `organizationId` rules as `list`.
471
534
  */
472
- async delete(organizationId, productId) {
473
- await this.http.delete(
474
- `organizations/${organizationId}/products/${productId}`
475
- );
535
+ async delete(productId, organizationId) {
536
+ await this.http.delete(`products/${productId}`, {
537
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
538
+ });
476
539
  }
477
540
  /**
478
541
  * Bulk import products/services from a CSV file (multipart/form-data,
@@ -485,16 +548,19 @@ var ProductsResource = class {
485
548
  * even if other rows fail, and every failure is reported with its row
486
549
  * number and reason.
487
550
  *
488
- * Calls POST /organizations/:organizationId/products/import
551
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
489
552
  */
490
- async importCsv(organizationId, file, filename = "products.csv") {
553
+ async importCsv(file, filename = "products.csv", organizationId) {
491
554
  const formData = new FormData();
492
555
  formData.append("file", file, filename);
493
- return this.http.post(`organizations/${organizationId}/products/import`, {
556
+ return this.http.post("products/import", {
494
557
  body: formData,
495
558
  // Let fetch set the multipart Content-Type (with boundary) itself —
496
559
  // unset the JSON default header inherited from the client instance.
497
- headers: { "Content-Type": void 0 }
560
+ headers: {
561
+ "Content-Type": void 0,
562
+ ...organizationId ? { "X-Organization-Id": organizationId } : void 0
563
+ }
498
564
  }).json();
499
565
  }
500
566
  };
@@ -655,14 +721,17 @@ var Timbrix = class {
655
721
  sat;
656
722
  invoices;
657
723
  constructor(config = {}) {
658
- const baseUrl = config.baseUrl || "http://localhost:3001";
724
+ const baseUrl = (config.baseUrl || "http://localhost:3001").replace(
725
+ /\/?$/,
726
+ "/"
727
+ );
659
728
  if (config.bearerToken) {
660
729
  this.authStrategy = new BearerAuth(config.bearerToken);
661
730
  } else if (config.apiKey) {
662
731
  this.authStrategy = new ApiKeyAuth(config.apiKey);
663
732
  }
664
733
  this.http = import_ky.default.create({
665
- prefixUrl: baseUrl,
734
+ baseUrl,
666
735
  headers: {
667
736
  "Content-Type": "application/json"
668
737
  },
package/dist/index.mjs CHANGED
@@ -124,38 +124,49 @@ var CustomersResource = class {
124
124
  }
125
125
  http;
126
126
  /**
127
- * List all customers for an organization
127
+ * List all customers. Works with either an API key (organization
128
+ * resolved from the key — omit `organizationId`) or a Supabase bearer
129
+ * session (pass `organizationId` explicitly; sent as the
130
+ * `X-Organization-Id` header).
128
131
  */
129
132
  async list(organizationId) {
130
- return this.http.get(`organizations/${organizationId}/customers`).json();
133
+ return this.http.get("customers", {
134
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
135
+ }).json();
131
136
  }
132
137
  /**
133
- * Get a customer by ID
138
+ * Get a customer by ID. Same `organizationId` rules as `list`.
134
139
  */
135
- async get(organizationId, customerId) {
136
- return this.http.get(`organizations/${organizationId}/customers/${customerId}`).json();
140
+ async get(customerId, organizationId) {
141
+ return this.http.get(`customers/${customerId}`, {
142
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
143
+ }).json();
137
144
  }
138
145
  /**
139
- * Create a new customer
146
+ * Create a new customer. Same `organizationId` rules as `list`.
140
147
  */
141
- async create(organizationId, data) {
142
- return this.http.post(`organizations/${organizationId}/customers`, { json: data }).json();
148
+ async create(data, organizationId) {
149
+ return this.http.post("customers", {
150
+ json: data,
151
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
152
+ }).json();
143
153
  }
144
154
  /**
145
- * Update a customer
155
+ * Update a customer. Same `organizationId` rules as `list`.
146
156
  */
147
- async update(organizationId, customerId, data) {
148
- return this.http.put(`organizations/${organizationId}/customers/${customerId}`, {
149
- json: data
157
+ async update(customerId, data, organizationId) {
158
+ return this.http.put(`customers/${customerId}`, {
159
+ json: data,
160
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
150
161
  }).json();
151
162
  }
152
163
  /**
153
- * Delete a customer
164
+ * Delete a customer. Same `organizationId` rules as `list`.
154
165
  */
155
- async delete(organizationId, customerId) {
156
- await this.http.delete(
157
- `organizations/${organizationId}/customers/${customerId}`
158
- );
166
+ async delete(customerId, organizationId) {
167
+ await this.http.delete(`customers/${customerId}`, {
168
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
169
+ });
159
170
  }
160
171
  };
161
172
 
@@ -167,27 +178,46 @@ var InvoicesResource = class {
167
178
  http;
168
179
  /**
169
180
  * Create and stamp (timbrar) a CFDI 4.0 invoice via the configured PAC.
170
- * Works with either a Supabase bearer session (internal dashboard, the
171
- * user must be a member of `organizationId`) or an API key (external
172
- * integrations, requires the `write:invoices` scope — the key must
173
- * belong to `organizationId`).
181
+ * Works with either a Supabase bearer session (pass `organizationId`,
182
+ * the user must be a member of it) or an API key (external
183
+ * integrations, requires the `write:invoices` scope)when the client
184
+ * is authenticated with an API key, `organizationId` can be omitted and
185
+ * is resolved from the key itself. When provided, sent as the
186
+ * `X-Organization-Id` header.
187
+ */
188
+ async create(data, organizationId) {
189
+ return this.http.post("invoices", {
190
+ json: data,
191
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
192
+ }).json();
193
+ }
194
+ /**
195
+ * Generate a PDF preview of a CFDI 4.0 invoice without stamping
196
+ * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
197
+ * is consumed. Accepts the same body shape as `create`. Same auth rules
198
+ * as `create` — `organizationId` is optional when authenticated with an
199
+ * API key. When provided, sent as the `X-Organization-Id` header.
174
200
  */
175
- async create(organizationId, data) {
176
- return this.http.post(`organizations/${organizationId}/invoices`, { json: data }).json();
201
+ async previewPdf(data, organizationId) {
202
+ return this.http.post("invoices/preview/pdf", {
203
+ json: data,
204
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
205
+ }).blob();
177
206
  }
178
207
  /**
179
- * List invoices for an organization, newest first. Works with either a
180
- * Supabase bearer session or an API key (requires the `read:invoices`
181
- * scope), same rules as `create`.
208
+ * List invoices for an organization, newest first. Same auth rules as
209
+ * `create` `organizationId` is optional when authenticated with an
210
+ * API key. When provided, sent as the `X-Organization-Id` header.
182
211
  */
183
- async list(organizationId, params) {
212
+ async list(params, organizationId) {
184
213
  const searchParams = {};
185
214
  if (params?.page !== void 0) searchParams.page = String(params.page);
186
215
  if (params?.limit !== void 0) searchParams.limit = String(params.limit);
187
216
  if (params?.type !== void 0) searchParams.type = params.type;
188
217
  if (params?.status !== void 0) searchParams.status = params.status;
189
- return this.http.get(`organizations/${organizationId}/invoices`, {
190
- searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0
218
+ return this.http.get("invoices", {
219
+ searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0,
220
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
191
221
  }).json();
192
222
  }
193
223
  /**
@@ -214,6 +244,29 @@ var InvoicesResource = class {
214
244
  async getPdf(uuid) {
215
245
  return this.http.get(`invoices/${uuid}/pdf`).blob();
216
246
  }
247
+ /**
248
+ * Cancel a stamped CFDI 4.0 invoice per SAT rules. Works with either a
249
+ * Supabase bearer session or an API key (requires the `write:invoices`
250
+ * scope). Returns immediately with `cancellationStatus: "pendiente"`
251
+ * when the SAT requires receptor approval — Timbrix cannot confirm that
252
+ * approval in real time.
253
+ */
254
+ async cancel(uuid, data) {
255
+ return this.http.post(`invoices/${uuid}/cancel`, { json: data }).json();
256
+ }
257
+ /**
258
+ * Get how many CFDI the organization has stamped this calendar month
259
+ * (Mexico City time) against its plan's included quota. `cfdiIncluded`
260
+ * and `cfdiRemaining` are `null` for the enterprise plan (unlimited).
261
+ * `organizationId` is optional when authenticated with an API key
262
+ * (resolved from the key). When provided, sent as the `X-Organization-Id`
263
+ * header.
264
+ */
265
+ async usage(organizationId) {
266
+ return this.http.get("usage", {
267
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
268
+ }).json();
269
+ }
217
270
  };
218
271
 
219
272
  // src/resources/oauth.ts
@@ -386,45 +439,55 @@ var ProductsResource = class {
386
439
  }
387
440
  http;
388
441
  /**
389
- * List products for an organization, with optional filters
442
+ * List products, with optional filters. Works with either an API key
443
+ * (organization resolved from the key — omit `organizationId`) or a
444
+ * Supabase bearer session (pass `organizationId` explicitly; sent as the
445
+ * `X-Organization-Id` header).
390
446
  */
391
- async list(organizationId, filters) {
447
+ async list(filters, organizationId) {
392
448
  const searchParams = {};
393
449
  if (filters?.description) searchParams.description = filters.description;
394
450
  if (filters?.sku) searchParams.sku = filters.sku;
395
451
  if (filters?.productKey !== void 0)
396
452
  searchParams.productKey = String(filters.productKey);
397
- return this.http.get(`organizations/${organizationId}/products`, {
398
- searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0
453
+ return this.http.get("products", {
454
+ searchParams: Object.keys(searchParams).length > 0 ? searchParams : void 0,
455
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
399
456
  }).json();
400
457
  }
401
458
  /**
402
- * Get a product by ID
459
+ * Get a product by ID. Same `organizationId` rules as `list`.
403
460
  */
404
- async get(organizationId, productId) {
405
- return this.http.get(`organizations/${organizationId}/products/${productId}`).json();
461
+ async get(productId, organizationId) {
462
+ return this.http.get(`products/${productId}`, {
463
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
464
+ }).json();
406
465
  }
407
466
  /**
408
- * Create a new product or service
467
+ * Create a new product or service. Same `organizationId` rules as `list`.
409
468
  */
410
- async create(organizationId, data) {
411
- return this.http.post(`organizations/${organizationId}/products`, { json: data }).json();
469
+ async create(data, organizationId) {
470
+ return this.http.post("products", {
471
+ json: data,
472
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
473
+ }).json();
412
474
  }
413
475
  /**
414
- * Update a product
476
+ * Update a product. Same `organizationId` rules as `list`.
415
477
  */
416
- async update(organizationId, productId, data) {
417
- return this.http.put(`organizations/${organizationId}/products/${productId}`, {
418
- json: data
478
+ async update(productId, data, organizationId) {
479
+ return this.http.put(`products/${productId}`, {
480
+ json: data,
481
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
419
482
  }).json();
420
483
  }
421
484
  /**
422
- * Delete a product
485
+ * Delete a product. Same `organizationId` rules as `list`.
423
486
  */
424
- async delete(organizationId, productId) {
425
- await this.http.delete(
426
- `organizations/${organizationId}/products/${productId}`
427
- );
487
+ async delete(productId, organizationId) {
488
+ await this.http.delete(`products/${productId}`, {
489
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
490
+ });
428
491
  }
429
492
  /**
430
493
  * Bulk import products/services from a CSV file (multipart/form-data,
@@ -437,16 +500,19 @@ var ProductsResource = class {
437
500
  * even if other rows fail, and every failure is reported with its row
438
501
  * number and reason.
439
502
  *
440
- * Calls POST /organizations/:organizationId/products/import
503
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
441
504
  */
442
- async importCsv(organizationId, file, filename = "products.csv") {
505
+ async importCsv(file, filename = "products.csv", organizationId) {
443
506
  const formData = new FormData();
444
507
  formData.append("file", file, filename);
445
- return this.http.post(`organizations/${organizationId}/products/import`, {
508
+ return this.http.post("products/import", {
446
509
  body: formData,
447
510
  // Let fetch set the multipart Content-Type (with boundary) itself —
448
511
  // unset the JSON default header inherited from the client instance.
449
- headers: { "Content-Type": void 0 }
512
+ headers: {
513
+ "Content-Type": void 0,
514
+ ...organizationId ? { "X-Organization-Id": organizationId } : void 0
515
+ }
450
516
  }).json();
451
517
  }
452
518
  };
@@ -607,14 +673,17 @@ var Timbrix = class {
607
673
  sat;
608
674
  invoices;
609
675
  constructor(config = {}) {
610
- const baseUrl = config.baseUrl || "http://localhost:3001";
676
+ const baseUrl = (config.baseUrl || "http://localhost:3001").replace(
677
+ /\/?$/,
678
+ "/"
679
+ );
611
680
  if (config.bearerToken) {
612
681
  this.authStrategy = new BearerAuth(config.bearerToken);
613
682
  } else if (config.apiKey) {
614
683
  this.authStrategy = new ApiKeyAuth(config.apiKey);
615
684
  }
616
685
  this.http = ky.create({
617
- prefixUrl: baseUrl,
686
+ baseUrl,
618
687
  headers: {
619
688
  "Content-Type": "application/json"
620
689
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timbrix/sdk",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "description": "TypeScript SDK for Timbrix API",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",