@timbrix/sdk 1.4.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,28 +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
674
  * Generate a PDF preview of a CFDI 4.0 invoice without stamping
643
675
  * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
644
- * is consumed. Accepts the same body shape as `create`. Works with
645
- * either a Supabase bearer session (internal dashboard, the user must
646
- * be a member of `organizationId`) or an API key (external
647
- * integrations, requires the `write:invoices` scope — the key must
648
- * belong to `organizationId`).
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.
649
679
  */
650
- previewPdf(organizationId: string, data: CreateInvoiceInput): Promise<Blob>;
680
+ previewPdf(data: CreateInvoiceInput, organizationId?: string): Promise<Blob>;
651
681
  /**
652
- * List invoices for an organization, newest first. Works with either a
653
- * Supabase bearer session or an API key (requires the `read:invoices`
654
- * scope), same rules as `create`.
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.
655
685
  */
656
- list(organizationId: string, params?: ListInvoicesParams): Promise<ListInvoicesResponse>;
686
+ list(params?: ListInvoicesParams, organizationId?: string): Promise<ListInvoicesResponse>;
657
687
  /**
658
688
  * Get a single CFDI 4.0 invoice by its folio fiscal (UUID). Works with
659
689
  * either a Supabase bearer session or an API key (requires the
@@ -672,6 +702,23 @@ declare class InvoicesResource {
672
702
  * scope).
673
703
  */
674
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>;
675
722
  }
676
723
 
677
724
  declare class OAuthResource {
@@ -772,25 +819,28 @@ declare class ProductsResource {
772
819
  private http;
773
820
  constructor(http: KyInstance);
774
821
  /**
775
- * 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).
776
826
  */
777
- list(organizationId: string, filters?: ListProductsFilters): Promise<Product[]>;
827
+ list(filters?: ListProductsFilters, organizationId?: string): Promise<Product[]>;
778
828
  /**
779
- * Get a product by ID
829
+ * Get a product by ID. Same `organizationId` rules as `list`.
780
830
  */
781
- get(organizationId: string, productId: string): Promise<Product>;
831
+ get(productId: string, organizationId?: string): Promise<Product>;
782
832
  /**
783
- * Create a new product or service
833
+ * Create a new product or service. Same `organizationId` rules as `list`.
784
834
  */
785
- create(organizationId: string, data: CreateProductInput): Promise<Product>;
835
+ create(data: CreateProductInput, organizationId?: string): Promise<Product>;
786
836
  /**
787
- * Update a product
837
+ * Update a product. Same `organizationId` rules as `list`.
788
838
  */
789
- update(organizationId: string, productId: string, data: UpdateProductInput): Promise<Product>;
839
+ update(productId: string, data: UpdateProductInput, organizationId?: string): Promise<Product>;
790
840
  /**
791
- * Delete a product
841
+ * Delete a product. Same `organizationId` rules as `list`.
792
842
  */
793
- delete(organizationId: string, productId: string): Promise<void>;
843
+ delete(productId: string, organizationId?: string): Promise<void>;
794
844
  /**
795
845
  * Bulk import products/services from a CSV file (multipart/form-data,
796
846
  * field name "file"). Works in both Node (18+) and browser environments,
@@ -802,9 +852,9 @@ declare class ProductsResource {
802
852
  * even if other rows fail, and every failure is reported with its row
803
853
  * number and reason.
804
854
  *
805
- * Calls POST /organizations/:organizationId/products/import
855
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
806
856
  */
807
- importCsv(organizationId: string, file: Blob | File, filename?: string): Promise<ImportProductsCsvResult>;
857
+ importCsv(file: Blob | File, filename?: string, organizationId?: string): Promise<ImportProductsCsvResult>;
808
858
  }
809
859
 
810
860
  declare class SatResource {
@@ -929,4 +979,4 @@ declare class ApiKeyAuth implements AuthStrategy {
929
979
  applyAuth(options: Options): Options;
930
980
  }
931
981
 
932
- 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,28 +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
674
  * Generate a PDF preview of a CFDI 4.0 invoice without stamping
643
675
  * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
644
- * is consumed. Accepts the same body shape as `create`. Works with
645
- * either a Supabase bearer session (internal dashboard, the user must
646
- * be a member of `organizationId`) or an API key (external
647
- * integrations, requires the `write:invoices` scope — the key must
648
- * belong to `organizationId`).
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.
649
679
  */
650
- previewPdf(organizationId: string, data: CreateInvoiceInput): Promise<Blob>;
680
+ previewPdf(data: CreateInvoiceInput, organizationId?: string): Promise<Blob>;
651
681
  /**
652
- * List invoices for an organization, newest first. Works with either a
653
- * Supabase bearer session or an API key (requires the `read:invoices`
654
- * scope), same rules as `create`.
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.
655
685
  */
656
- list(organizationId: string, params?: ListInvoicesParams): Promise<ListInvoicesResponse>;
686
+ list(params?: ListInvoicesParams, organizationId?: string): Promise<ListInvoicesResponse>;
657
687
  /**
658
688
  * Get a single CFDI 4.0 invoice by its folio fiscal (UUID). Works with
659
689
  * either a Supabase bearer session or an API key (requires the
@@ -672,6 +702,23 @@ declare class InvoicesResource {
672
702
  * scope).
673
703
  */
674
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>;
675
722
  }
676
723
 
677
724
  declare class OAuthResource {
@@ -772,25 +819,28 @@ declare class ProductsResource {
772
819
  private http;
773
820
  constructor(http: KyInstance);
774
821
  /**
775
- * 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).
776
826
  */
777
- list(organizationId: string, filters?: ListProductsFilters): Promise<Product[]>;
827
+ list(filters?: ListProductsFilters, organizationId?: string): Promise<Product[]>;
778
828
  /**
779
- * Get a product by ID
829
+ * Get a product by ID. Same `organizationId` rules as `list`.
780
830
  */
781
- get(organizationId: string, productId: string): Promise<Product>;
831
+ get(productId: string, organizationId?: string): Promise<Product>;
782
832
  /**
783
- * Create a new product or service
833
+ * Create a new product or service. Same `organizationId` rules as `list`.
784
834
  */
785
- create(organizationId: string, data: CreateProductInput): Promise<Product>;
835
+ create(data: CreateProductInput, organizationId?: string): Promise<Product>;
786
836
  /**
787
- * Update a product
837
+ * Update a product. Same `organizationId` rules as `list`.
788
838
  */
789
- update(organizationId: string, productId: string, data: UpdateProductInput): Promise<Product>;
839
+ update(productId: string, data: UpdateProductInput, organizationId?: string): Promise<Product>;
790
840
  /**
791
- * Delete a product
841
+ * Delete a product. Same `organizationId` rules as `list`.
792
842
  */
793
- delete(organizationId: string, productId: string): Promise<void>;
843
+ delete(productId: string, organizationId?: string): Promise<void>;
794
844
  /**
795
845
  * Bulk import products/services from a CSV file (multipart/form-data,
796
846
  * field name "file"). Works in both Node (18+) and browser environments,
@@ -802,9 +852,9 @@ declare class ProductsResource {
802
852
  * even if other rows fail, and every failure is reported with its row
803
853
  * number and reason.
804
854
  *
805
- * Calls POST /organizations/:organizationId/products/import
855
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
806
856
  */
807
- importCsv(organizationId: string, file: Blob | File, filename?: string): Promise<ImportProductsCsvResult>;
857
+ importCsv(file: Blob | File, filename?: string, organizationId?: string): Promise<ImportProductsCsvResult>;
808
858
  }
809
859
 
810
860
  declare class SatResource {
@@ -929,4 +979,4 @@ declare class ApiKeyAuth implements AuthStrategy {
929
979
  applyAuth(options: Options): Options;
930
980
  }
931
981
 
932
- 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,41 +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`).
222
- */
223
- async create(organizationId, data) {
224
- return this.http.post(`organizations/${organizationId}/invoices`, { json: data }).json();
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();
225
241
  }
226
242
  /**
227
243
  * Generate a PDF preview of a CFDI 4.0 invoice without stamping
228
244
  * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
229
- * is consumed. Accepts the same body shape as `create`. Works with
230
- * either a Supabase bearer session (internal dashboard, the user must
231
- * be a member of `organizationId`) or an API key (external
232
- * integrations, requires the `write:invoices` scope — the key must
233
- * belong to `organizationId`).
234
- */
235
- async previewPdf(organizationId, data) {
236
- return this.http.post(`organizations/${organizationId}/invoices/preview/pdf`, {
237
- json: data
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.
248
+ */
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
238
253
  }).blob();
239
254
  }
240
255
  /**
241
- * List invoices for an organization, newest first. Works with either a
242
- * Supabase bearer session or an API key (requires the `read:invoices`
243
- * 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.
244
259
  */
245
- async list(organizationId, params) {
260
+ async list(params, organizationId) {
246
261
  const searchParams = {};
247
262
  if (params?.page !== void 0) searchParams.page = String(params.page);
248
263
  if (params?.limit !== void 0) searchParams.limit = String(params.limit);
249
264
  if (params?.type !== void 0) searchParams.type = params.type;
250
265
  if (params?.status !== void 0) searchParams.status = params.status;
251
- return this.http.get(`organizations/${organizationId}/invoices`, {
252
- 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
253
269
  }).json();
254
270
  }
255
271
  /**
@@ -276,6 +292,29 @@ var InvoicesResource = class {
276
292
  async getPdf(uuid) {
277
293
  return this.http.get(`invoices/${uuid}/pdf`).blob();
278
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
+ }
279
318
  };
280
319
 
281
320
  // src/resources/oauth.ts
@@ -448,45 +487,55 @@ var ProductsResource = class {
448
487
  }
449
488
  http;
450
489
  /**
451
- * 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).
452
494
  */
453
- async list(organizationId, filters) {
495
+ async list(filters, organizationId) {
454
496
  const searchParams = {};
455
497
  if (filters?.description) searchParams.description = filters.description;
456
498
  if (filters?.sku) searchParams.sku = filters.sku;
457
499
  if (filters?.productKey !== void 0)
458
500
  searchParams.productKey = String(filters.productKey);
459
- return this.http.get(`organizations/${organizationId}/products`, {
460
- 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
461
504
  }).json();
462
505
  }
463
506
  /**
464
- * Get a product by ID
507
+ * Get a product by ID. Same `organizationId` rules as `list`.
465
508
  */
466
- async get(organizationId, productId) {
467
- 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();
468
513
  }
469
514
  /**
470
- * Create a new product or service
515
+ * Create a new product or service. Same `organizationId` rules as `list`.
471
516
  */
472
- async create(organizationId, data) {
473
- 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();
474
522
  }
475
523
  /**
476
- * Update a product
524
+ * Update a product. Same `organizationId` rules as `list`.
477
525
  */
478
- async update(organizationId, productId, data) {
479
- return this.http.put(`organizations/${organizationId}/products/${productId}`, {
480
- 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
481
530
  }).json();
482
531
  }
483
532
  /**
484
- * Delete a product
533
+ * Delete a product. Same `organizationId` rules as `list`.
485
534
  */
486
- async delete(organizationId, productId) {
487
- await this.http.delete(
488
- `organizations/${organizationId}/products/${productId}`
489
- );
535
+ async delete(productId, organizationId) {
536
+ await this.http.delete(`products/${productId}`, {
537
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
538
+ });
490
539
  }
491
540
  /**
492
541
  * Bulk import products/services from a CSV file (multipart/form-data,
@@ -499,16 +548,19 @@ var ProductsResource = class {
499
548
  * even if other rows fail, and every failure is reported with its row
500
549
  * number and reason.
501
550
  *
502
- * Calls POST /organizations/:organizationId/products/import
551
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
503
552
  */
504
- async importCsv(organizationId, file, filename = "products.csv") {
553
+ async importCsv(file, filename = "products.csv", organizationId) {
505
554
  const formData = new FormData();
506
555
  formData.append("file", file, filename);
507
- return this.http.post(`organizations/${organizationId}/products/import`, {
556
+ return this.http.post("products/import", {
508
557
  body: formData,
509
558
  // Let fetch set the multipart Content-Type (with boundary) itself —
510
559
  // unset the JSON default header inherited from the client instance.
511
- headers: { "Content-Type": void 0 }
560
+ headers: {
561
+ "Content-Type": void 0,
562
+ ...organizationId ? { "X-Organization-Id": organizationId } : void 0
563
+ }
512
564
  }).json();
513
565
  }
514
566
  };
@@ -669,14 +721,17 @@ var Timbrix = class {
669
721
  sat;
670
722
  invoices;
671
723
  constructor(config = {}) {
672
- const baseUrl = config.baseUrl || "http://localhost:3001";
724
+ const baseUrl = (config.baseUrl || "http://localhost:3001").replace(
725
+ /\/?$/,
726
+ "/"
727
+ );
673
728
  if (config.bearerToken) {
674
729
  this.authStrategy = new BearerAuth(config.bearerToken);
675
730
  } else if (config.apiKey) {
676
731
  this.authStrategy = new ApiKeyAuth(config.apiKey);
677
732
  }
678
733
  this.http = import_ky.default.create({
679
- prefixUrl: baseUrl,
734
+ baseUrl,
680
735
  headers: {
681
736
  "Content-Type": "application/json"
682
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,41 +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`).
174
- */
175
- async create(organizationId, data) {
176
- return this.http.post(`organizations/${organizationId}/invoices`, { json: data }).json();
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();
177
193
  }
178
194
  /**
179
195
  * Generate a PDF preview of a CFDI 4.0 invoice without stamping
180
196
  * (timbrar) it via the PAC. Nothing is persisted and no stamping quota
181
- * is consumed. Accepts the same body shape as `create`. Works with
182
- * either a Supabase bearer session (internal dashboard, the user must
183
- * be a member of `organizationId`) or an API key (external
184
- * integrations, requires the `write:invoices` scope — the key must
185
- * belong to `organizationId`).
186
- */
187
- async previewPdf(organizationId, data) {
188
- return this.http.post(`organizations/${organizationId}/invoices/preview/pdf`, {
189
- json: data
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.
200
+ */
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
190
205
  }).blob();
191
206
  }
192
207
  /**
193
- * List invoices for an organization, newest first. Works with either a
194
- * Supabase bearer session or an API key (requires the `read:invoices`
195
- * 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.
196
211
  */
197
- async list(organizationId, params) {
212
+ async list(params, organizationId) {
198
213
  const searchParams = {};
199
214
  if (params?.page !== void 0) searchParams.page = String(params.page);
200
215
  if (params?.limit !== void 0) searchParams.limit = String(params.limit);
201
216
  if (params?.type !== void 0) searchParams.type = params.type;
202
217
  if (params?.status !== void 0) searchParams.status = params.status;
203
- return this.http.get(`organizations/${organizationId}/invoices`, {
204
- 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
205
221
  }).json();
206
222
  }
207
223
  /**
@@ -228,6 +244,29 @@ var InvoicesResource = class {
228
244
  async getPdf(uuid) {
229
245
  return this.http.get(`invoices/${uuid}/pdf`).blob();
230
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
+ }
231
270
  };
232
271
 
233
272
  // src/resources/oauth.ts
@@ -400,45 +439,55 @@ var ProductsResource = class {
400
439
  }
401
440
  http;
402
441
  /**
403
- * 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).
404
446
  */
405
- async list(organizationId, filters) {
447
+ async list(filters, organizationId) {
406
448
  const searchParams = {};
407
449
  if (filters?.description) searchParams.description = filters.description;
408
450
  if (filters?.sku) searchParams.sku = filters.sku;
409
451
  if (filters?.productKey !== void 0)
410
452
  searchParams.productKey = String(filters.productKey);
411
- return this.http.get(`organizations/${organizationId}/products`, {
412
- 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
413
456
  }).json();
414
457
  }
415
458
  /**
416
- * Get a product by ID
459
+ * Get a product by ID. Same `organizationId` rules as `list`.
417
460
  */
418
- async get(organizationId, productId) {
419
- 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();
420
465
  }
421
466
  /**
422
- * Create a new product or service
467
+ * Create a new product or service. Same `organizationId` rules as `list`.
423
468
  */
424
- async create(organizationId, data) {
425
- 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();
426
474
  }
427
475
  /**
428
- * Update a product
476
+ * Update a product. Same `organizationId` rules as `list`.
429
477
  */
430
- async update(organizationId, productId, data) {
431
- return this.http.put(`organizations/${organizationId}/products/${productId}`, {
432
- 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
433
482
  }).json();
434
483
  }
435
484
  /**
436
- * Delete a product
485
+ * Delete a product. Same `organizationId` rules as `list`.
437
486
  */
438
- async delete(organizationId, productId) {
439
- await this.http.delete(
440
- `organizations/${organizationId}/products/${productId}`
441
- );
487
+ async delete(productId, organizationId) {
488
+ await this.http.delete(`products/${productId}`, {
489
+ headers: organizationId ? { "X-Organization-Id": organizationId } : void 0
490
+ });
442
491
  }
443
492
  /**
444
493
  * Bulk import products/services from a CSV file (multipart/form-data,
@@ -451,16 +500,19 @@ var ProductsResource = class {
451
500
  * even if other rows fail, and every failure is reported with its row
452
501
  * number and reason.
453
502
  *
454
- * Calls POST /organizations/:organizationId/products/import
503
+ * Calls POST /products/import. Same `organizationId` rules as `list`.
455
504
  */
456
- async importCsv(organizationId, file, filename = "products.csv") {
505
+ async importCsv(file, filename = "products.csv", organizationId) {
457
506
  const formData = new FormData();
458
507
  formData.append("file", file, filename);
459
- return this.http.post(`organizations/${organizationId}/products/import`, {
508
+ return this.http.post("products/import", {
460
509
  body: formData,
461
510
  // Let fetch set the multipart Content-Type (with boundary) itself —
462
511
  // unset the JSON default header inherited from the client instance.
463
- headers: { "Content-Type": void 0 }
512
+ headers: {
513
+ "Content-Type": void 0,
514
+ ...organizationId ? { "X-Organization-Id": organizationId } : void 0
515
+ }
464
516
  }).json();
465
517
  }
466
518
  };
@@ -621,14 +673,17 @@ var Timbrix = class {
621
673
  sat;
622
674
  invoices;
623
675
  constructor(config = {}) {
624
- const baseUrl = config.baseUrl || "http://localhost:3001";
676
+ const baseUrl = (config.baseUrl || "http://localhost:3001").replace(
677
+ /\/?$/,
678
+ "/"
679
+ );
625
680
  if (config.bearerToken) {
626
681
  this.authStrategy = new BearerAuth(config.bearerToken);
627
682
  } else if (config.apiKey) {
628
683
  this.authStrategy = new ApiKeyAuth(config.apiKey);
629
684
  }
630
685
  this.http = ky.create({
631
- prefixUrl: baseUrl,
686
+ baseUrl,
632
687
  headers: {
633
688
  "Content-Type": "application/json"
634
689
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timbrix/sdk",
3
- "version": "1.4.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",