factuplan 0.2.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -152,6 +152,35 @@ const status = await factuplan.invoices.getStatus(result.id);
152
152
  const { url } = await factuplan.invoices.downloadXml(result.id);
153
153
  ```
154
154
 
155
+ ### Solo firmar XML (Modo C)
156
+
157
+ Firma el XML con tu certificado sin enviarlo al SRI:
158
+
159
+ ```typescript
160
+ const { signedXml } = await factuplan.invoices.signOnly({ xml });
161
+ ```
162
+
163
+ ### Validar XML
164
+
165
+ Valida la estructura de un XML sin procesarlo:
166
+
167
+ ```typescript
168
+ const { valid, errors } = await factuplan.invoices.validateXml({ xml });
169
+ if (!valid) {
170
+ console.log('Errores:', errors);
171
+ }
172
+ ```
173
+
174
+ ### Verificar autorizacion
175
+
176
+ Consulta el estado de autorizacion de un comprobante por su clave de acceso:
177
+
178
+ ```typescript
179
+ const result = await factuplan.invoices.verify('0104202601099337815000110010010000000011234567890');
180
+ console.log(result.authorized); // true/false
181
+ console.log(result.authorizationNumber); // Numero de autorizacion
182
+ ```
183
+
155
184
  ### Uso y certificado
156
185
 
157
186
  ```typescript
package/dist/index.d.mts CHANGED
@@ -142,6 +142,30 @@ interface SignAndAuthorizeResponse {
142
142
  accessKey: string;
143
143
  status: string;
144
144
  }
145
+ interface SignOnlyInput {
146
+ /** Unsigned XML string */
147
+ xml: string;
148
+ }
149
+ interface SignOnlyResponse {
150
+ signedXml: string;
151
+ }
152
+ interface ValidateXmlInput {
153
+ /** XML string to validate */
154
+ xml: string;
155
+ }
156
+ interface ValidateXmlResponse {
157
+ valid: boolean;
158
+ errors: string[];
159
+ }
160
+ interface VerifyResponse {
161
+ authorized: boolean;
162
+ authorizationNumber?: string;
163
+ authorizationDate?: string;
164
+ messages?: Array<{
165
+ code?: string;
166
+ message?: string;
167
+ }>;
168
+ }
145
169
  interface UsageResponse {
146
170
  apiKeyId: string;
147
171
  month: string;
@@ -158,6 +182,24 @@ interface CertificateStatus {
158
182
  legalName?: string;
159
183
  expiresAt?: string;
160
184
  }
185
+ interface WebhookEvent {
186
+ id: string;
187
+ event: string;
188
+ timestamp: string;
189
+ data: WebhookReceiptData;
190
+ webhookId: string;
191
+ attempt: number;
192
+ }
193
+ interface WebhookReceiptData {
194
+ receiptId: string;
195
+ type: string;
196
+ accessKey: string;
197
+ authorizationNumber: string;
198
+ documentNumber: string;
199
+ total: string;
200
+ customerName: string;
201
+ customerIdentification: string;
202
+ }
161
203
  interface FactuplanOptions {
162
204
  /** Base URL of the API (default: https://api.factuplan.com/api/v1) */
163
205
  baseUrl?: string;
@@ -165,10 +207,10 @@ interface FactuplanOptions {
165
207
  timeout?: number;
166
208
  }
167
209
 
168
- type Requester$2 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
210
+ type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
169
211
  declare class CustomersResource {
170
212
  private request;
171
- constructor(request: Requester$2);
213
+ constructor(request: Requester$3);
172
214
  create(input: CreateCustomerInput): Promise<Customer>;
173
215
  list(params?: CustomerListParams): Promise<PaginatedResponse<Customer>>;
174
216
  get(id: string): Promise<Customer>;
@@ -176,22 +218,25 @@ declare class CustomersResource {
176
218
  delete(id: string): Promise<void>;
177
219
  }
178
220
 
179
- type Requester$1 = (method: string, path: string, body?: unknown) => Promise<unknown>;
221
+ type Requester$2 = (method: string, path: string, body?: unknown) => Promise<unknown>;
180
222
  declare class InvoicesResource {
181
223
  private request;
182
- constructor(request: Requester$1);
224
+ constructor(request: Requester$2);
183
225
  create(input: CreateInvoiceInput): Promise<Invoice>;
184
226
  signAndAuthorize(input: SignAndAuthorizeInput): Promise<SignAndAuthorizeResponse>;
227
+ signOnly(input: SignOnlyInput): Promise<SignOnlyResponse>;
228
+ validateXml(input: ValidateXmlInput): Promise<ValidateXmlResponse>;
229
+ verify(accessKey: string): Promise<VerifyResponse>;
185
230
  get(id: string): Promise<Record<string, unknown>>;
186
231
  getStatus(id: string): Promise<InvoiceStatus>;
187
232
  downloadXml(id: string): Promise<DownloadUrlResponse>;
188
233
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
189
234
  }
190
235
 
191
- type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
236
+ type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
192
237
  declare class ProductsResource {
193
238
  private request;
194
- constructor(request: Requester);
239
+ constructor(request: Requester$1);
195
240
  create(input: CreateProductInput): Promise<Product>;
196
241
  list(params?: ProductListParams): Promise<PaginatedResponse<Product>>;
197
242
  get(id: string): Promise<Product>;
@@ -199,6 +244,20 @@ declare class ProductsResource {
199
244
  delete(id: string): Promise<void>;
200
245
  }
201
246
 
247
+ type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
248
+ declare class WebhooksResource {
249
+ private readonly request;
250
+ constructor(requester: Requester);
251
+ /**
252
+ * Verify that a receipt (document) exists in the API.
253
+ * This is a second layer of verification beyond signature checking.
254
+ *
255
+ * @param receiptId - The receipt ID from the webhook payload
256
+ * @returns The receipt object if it exists, or `null` if not found
257
+ */
258
+ verifyReceipt(receiptId: string): Promise<Record<string, unknown> | null>;
259
+ }
260
+
202
261
  declare class Factuplan {
203
262
  private readonly apiKey;
204
263
  private readonly baseUrl;
@@ -206,6 +265,8 @@ declare class Factuplan {
206
265
  readonly customers: CustomersResource;
207
266
  readonly products: ProductsResource;
208
267
  readonly invoices: InvoicesResource;
268
+ readonly webhooks: WebhooksResource;
269
+ static readonly webhooks: typeof WebhooksResource;
209
270
  constructor(apiKey: string, options?: FactuplanOptions);
210
271
  usage(): Promise<UsageResponse>;
211
272
  certificateStatus(): Promise<CertificateStatus>;
@@ -225,4 +286,4 @@ declare class RateLimitError extends FactuplanError {
225
286
  constructor(message?: string);
226
287
  }
227
288
 
228
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse };
289
+ export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type WebhookEvent, type WebhookReceiptData };
package/dist/index.d.ts CHANGED
@@ -142,6 +142,30 @@ interface SignAndAuthorizeResponse {
142
142
  accessKey: string;
143
143
  status: string;
144
144
  }
145
+ interface SignOnlyInput {
146
+ /** Unsigned XML string */
147
+ xml: string;
148
+ }
149
+ interface SignOnlyResponse {
150
+ signedXml: string;
151
+ }
152
+ interface ValidateXmlInput {
153
+ /** XML string to validate */
154
+ xml: string;
155
+ }
156
+ interface ValidateXmlResponse {
157
+ valid: boolean;
158
+ errors: string[];
159
+ }
160
+ interface VerifyResponse {
161
+ authorized: boolean;
162
+ authorizationNumber?: string;
163
+ authorizationDate?: string;
164
+ messages?: Array<{
165
+ code?: string;
166
+ message?: string;
167
+ }>;
168
+ }
145
169
  interface UsageResponse {
146
170
  apiKeyId: string;
147
171
  month: string;
@@ -158,6 +182,24 @@ interface CertificateStatus {
158
182
  legalName?: string;
159
183
  expiresAt?: string;
160
184
  }
185
+ interface WebhookEvent {
186
+ id: string;
187
+ event: string;
188
+ timestamp: string;
189
+ data: WebhookReceiptData;
190
+ webhookId: string;
191
+ attempt: number;
192
+ }
193
+ interface WebhookReceiptData {
194
+ receiptId: string;
195
+ type: string;
196
+ accessKey: string;
197
+ authorizationNumber: string;
198
+ documentNumber: string;
199
+ total: string;
200
+ customerName: string;
201
+ customerIdentification: string;
202
+ }
161
203
  interface FactuplanOptions {
162
204
  /** Base URL of the API (default: https://api.factuplan.com/api/v1) */
163
205
  baseUrl?: string;
@@ -165,10 +207,10 @@ interface FactuplanOptions {
165
207
  timeout?: number;
166
208
  }
167
209
 
168
- type Requester$2 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
210
+ type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
169
211
  declare class CustomersResource {
170
212
  private request;
171
- constructor(request: Requester$2);
213
+ constructor(request: Requester$3);
172
214
  create(input: CreateCustomerInput): Promise<Customer>;
173
215
  list(params?: CustomerListParams): Promise<PaginatedResponse<Customer>>;
174
216
  get(id: string): Promise<Customer>;
@@ -176,22 +218,25 @@ declare class CustomersResource {
176
218
  delete(id: string): Promise<void>;
177
219
  }
178
220
 
179
- type Requester$1 = (method: string, path: string, body?: unknown) => Promise<unknown>;
221
+ type Requester$2 = (method: string, path: string, body?: unknown) => Promise<unknown>;
180
222
  declare class InvoicesResource {
181
223
  private request;
182
- constructor(request: Requester$1);
224
+ constructor(request: Requester$2);
183
225
  create(input: CreateInvoiceInput): Promise<Invoice>;
184
226
  signAndAuthorize(input: SignAndAuthorizeInput): Promise<SignAndAuthorizeResponse>;
227
+ signOnly(input: SignOnlyInput): Promise<SignOnlyResponse>;
228
+ validateXml(input: ValidateXmlInput): Promise<ValidateXmlResponse>;
229
+ verify(accessKey: string): Promise<VerifyResponse>;
185
230
  get(id: string): Promise<Record<string, unknown>>;
186
231
  getStatus(id: string): Promise<InvoiceStatus>;
187
232
  downloadXml(id: string): Promise<DownloadUrlResponse>;
188
233
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
189
234
  }
190
235
 
191
- type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
236
+ type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
192
237
  declare class ProductsResource {
193
238
  private request;
194
- constructor(request: Requester);
239
+ constructor(request: Requester$1);
195
240
  create(input: CreateProductInput): Promise<Product>;
196
241
  list(params?: ProductListParams): Promise<PaginatedResponse<Product>>;
197
242
  get(id: string): Promise<Product>;
@@ -199,6 +244,20 @@ declare class ProductsResource {
199
244
  delete(id: string): Promise<void>;
200
245
  }
201
246
 
247
+ type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
248
+ declare class WebhooksResource {
249
+ private readonly request;
250
+ constructor(requester: Requester);
251
+ /**
252
+ * Verify that a receipt (document) exists in the API.
253
+ * This is a second layer of verification beyond signature checking.
254
+ *
255
+ * @param receiptId - The receipt ID from the webhook payload
256
+ * @returns The receipt object if it exists, or `null` if not found
257
+ */
258
+ verifyReceipt(receiptId: string): Promise<Record<string, unknown> | null>;
259
+ }
260
+
202
261
  declare class Factuplan {
203
262
  private readonly apiKey;
204
263
  private readonly baseUrl;
@@ -206,6 +265,8 @@ declare class Factuplan {
206
265
  readonly customers: CustomersResource;
207
266
  readonly products: ProductsResource;
208
267
  readonly invoices: InvoicesResource;
268
+ readonly webhooks: WebhooksResource;
269
+ static readonly webhooks: typeof WebhooksResource;
209
270
  constructor(apiKey: string, options?: FactuplanOptions);
210
271
  usage(): Promise<UsageResponse>;
211
272
  certificateStatus(): Promise<CertificateStatus>;
@@ -225,4 +286,4 @@ declare class RateLimitError extends FactuplanError {
225
286
  constructor(message?: string);
226
287
  }
227
288
 
228
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse };
289
+ export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type WebhookEvent, type WebhookReceiptData };
package/dist/index.js CHANGED
@@ -83,6 +83,15 @@ var InvoicesResource = class {
83
83
  async signAndAuthorize(input) {
84
84
  return this.request("POST", "/developer/sign-and-authorize", input);
85
85
  }
86
+ async signOnly(input) {
87
+ return this.request("POST", "/developer/sign", input);
88
+ }
89
+ async validateXml(input) {
90
+ return this.request("POST", "/developer/validate-xml", input);
91
+ }
92
+ async verify(accessKey) {
93
+ return this.request("GET", `/developer/verify/${accessKey}`);
94
+ }
86
95
  async get(id) {
87
96
  return this.request("GET", `/developer/receipts/${id}`);
88
97
  }
@@ -119,6 +128,28 @@ var ProductsResource = class {
119
128
  }
120
129
  };
121
130
 
131
+ // src/resources/webhooks.ts
132
+ var WebhooksResource = class {
133
+ constructor(requester) {
134
+ this.request = requester;
135
+ }
136
+ /**
137
+ * Verify that a receipt (document) exists in the API.
138
+ * This is a second layer of verification beyond signature checking.
139
+ *
140
+ * @param receiptId - The receipt ID from the webhook payload
141
+ * @returns The receipt object if it exists, or `null` if not found
142
+ */
143
+ async verifyReceipt(receiptId) {
144
+ try {
145
+ const result = await this.request("GET", `/developer/receipts/${receiptId}`);
146
+ return result ?? null;
147
+ } catch {
148
+ return null;
149
+ }
150
+ }
151
+ };
152
+
122
153
  // src/client.ts
123
154
  var DEFAULT_BASE_URL = "https://api-rest.factuplan.com.ec/api/v1";
124
155
  var DEFAULT_TIMEOUT = 3e4;
@@ -132,6 +163,7 @@ var Factuplan = class {
132
163
  this.customers = new CustomersResource(requester);
133
164
  this.products = new ProductsResource(requester);
134
165
  this.invoices = new InvoicesResource(requester);
166
+ this.webhooks = new WebhooksResource(requester);
135
167
  }
136
168
  async usage() {
137
169
  return this.request("GET", "/developer/usage");
@@ -185,6 +217,7 @@ var Factuplan = class {
185
217
  return json;
186
218
  }
187
219
  };
220
+ Factuplan.webhooks = WebhooksResource;
188
221
  // Annotate the CommonJS export names for ESM import in node:
189
222
  0 && (module.exports = {
190
223
  AuthenticationError,
package/dist/index.mjs CHANGED
@@ -54,6 +54,15 @@ var InvoicesResource = class {
54
54
  async signAndAuthorize(input) {
55
55
  return this.request("POST", "/developer/sign-and-authorize", input);
56
56
  }
57
+ async signOnly(input) {
58
+ return this.request("POST", "/developer/sign", input);
59
+ }
60
+ async validateXml(input) {
61
+ return this.request("POST", "/developer/validate-xml", input);
62
+ }
63
+ async verify(accessKey) {
64
+ return this.request("GET", `/developer/verify/${accessKey}`);
65
+ }
57
66
  async get(id) {
58
67
  return this.request("GET", `/developer/receipts/${id}`);
59
68
  }
@@ -90,6 +99,28 @@ var ProductsResource = class {
90
99
  }
91
100
  };
92
101
 
102
+ // src/resources/webhooks.ts
103
+ var WebhooksResource = class {
104
+ constructor(requester) {
105
+ this.request = requester;
106
+ }
107
+ /**
108
+ * Verify that a receipt (document) exists in the API.
109
+ * This is a second layer of verification beyond signature checking.
110
+ *
111
+ * @param receiptId - The receipt ID from the webhook payload
112
+ * @returns The receipt object if it exists, or `null` if not found
113
+ */
114
+ async verifyReceipt(receiptId) {
115
+ try {
116
+ const result = await this.request("GET", `/developer/receipts/${receiptId}`);
117
+ return result ?? null;
118
+ } catch {
119
+ return null;
120
+ }
121
+ }
122
+ };
123
+
93
124
  // src/client.ts
94
125
  var DEFAULT_BASE_URL = "https://api-rest.factuplan.com.ec/api/v1";
95
126
  var DEFAULT_TIMEOUT = 3e4;
@@ -103,6 +134,7 @@ var Factuplan = class {
103
134
  this.customers = new CustomersResource(requester);
104
135
  this.products = new ProductsResource(requester);
105
136
  this.invoices = new InvoicesResource(requester);
137
+ this.webhooks = new WebhooksResource(requester);
106
138
  }
107
139
  async usage() {
108
140
  return this.request("GET", "/developer/usage");
@@ -156,6 +188,7 @@ var Factuplan = class {
156
188
  return json;
157
189
  }
158
190
  };
191
+ Factuplan.webhooks = WebhooksResource;
159
192
  export {
160
193
  AuthenticationError,
161
194
  Factuplan,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "factuplan",
3
- "version": "0.2.2",
3
+ "version": "0.4.1",
4
4
  "description": "Official Factuplan SDK for JavaScript & TypeScript — Create electronic invoices for Ecuador (SRI)",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -16,6 +16,7 @@
16
16
  "dist"
17
17
  ],
18
18
  "devDependencies": {
19
+ "@types/node": "^25.6.0",
19
20
  "tsup": "^8.0.0",
20
21
  "typescript": "^5.5.0"
21
22
  },