@beel_es/sdk 1.0.0 → 1.2.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/LICENSE +21 -0
- package/README.md +234 -74
- package/dist/index.d.mts +26774 -0
- package/dist/index.d.ts +26769 -21
- package/dist/index.js +1556 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1497 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +49 -19
- package/dist/client.d.ts +0 -54
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -94
- package/dist/client.js.map +0 -1
- package/dist/generated/client/client.gen.d.ts +0 -3
- package/dist/generated/client/client.gen.d.ts.map +0 -1
- package/dist/generated/client/client.gen.js +0 -240
- package/dist/generated/client/client.gen.js.map +0 -1
- package/dist/generated/client/index.d.ts +0 -9
- package/dist/generated/client/index.d.ts.map +0 -1
- package/dist/generated/client/index.js +0 -18
- package/dist/generated/client/index.js.map +0 -1
- package/dist/generated/client/types.gen.d.ts +0 -118
- package/dist/generated/client/types.gen.d.ts.map +0 -1
- package/dist/generated/client/types.gen.js +0 -4
- package/dist/generated/client/types.gen.js.map +0 -1
- package/dist/generated/client/utils.gen.d.ts +0 -34
- package/dist/generated/client/utils.gen.d.ts.map +0 -1
- package/dist/generated/client/utils.gen.js +0 -242
- package/dist/generated/client/utils.gen.js.map +0 -1
- package/dist/generated/client.gen.d.ts +0 -13
- package/dist/generated/client.gen.d.ts.map +0 -1
- package/dist/generated/client.gen.js +0 -7
- package/dist/generated/client.gen.js.map +0 -1
- package/dist/generated/core/auth.gen.d.ts +0 -19
- package/dist/generated/core/auth.gen.d.ts.map +0 -1
- package/dist/generated/core/auth.gen.js +0 -19
- package/dist/generated/core/auth.gen.js.map +0 -1
- package/dist/generated/core/bodySerializer.gen.d.ts +0 -26
- package/dist/generated/core/bodySerializer.gen.d.ts.map +0 -1
- package/dist/generated/core/bodySerializer.gen.js +0 -61
- package/dist/generated/core/bodySerializer.gen.js.map +0 -1
- package/dist/generated/core/params.gen.d.ts +0 -44
- package/dist/generated/core/params.gen.d.ts.map +0 -1
- package/dist/generated/core/params.gen.js +0 -105
- package/dist/generated/core/params.gen.js.map +0 -1
- package/dist/generated/core/pathSerializer.gen.d.ts +0 -34
- package/dist/generated/core/pathSerializer.gen.d.ts.map +0 -1
- package/dist/generated/core/pathSerializer.gen.js +0 -116
- package/dist/generated/core/pathSerializer.gen.js.map +0 -1
- package/dist/generated/core/queryKeySerializer.gen.d.ts +0 -19
- package/dist/generated/core/queryKeySerializer.gen.d.ts.map +0 -1
- package/dist/generated/core/queryKeySerializer.gen.js +0 -99
- package/dist/generated/core/queryKeySerializer.gen.js.map +0 -1
- package/dist/generated/core/serverSentEvents.gen.d.ts +0 -72
- package/dist/generated/core/serverSentEvents.gen.d.ts.map +0 -1
- package/dist/generated/core/serverSentEvents.gen.js +0 -138
- package/dist/generated/core/serverSentEvents.gen.js.map +0 -1
- package/dist/generated/core/types.gen.d.ts +0 -79
- package/dist/generated/core/types.gen.d.ts.map +0 -1
- package/dist/generated/core/types.gen.js +0 -4
- package/dist/generated/core/types.gen.js.map +0 -1
- package/dist/generated/core/utils.gen.d.ts +0 -20
- package/dist/generated/core/utils.gen.d.ts.map +0 -1
- package/dist/generated/core/utils.gen.js +0 -94
- package/dist/generated/core/utils.gen.js.map +0 -1
- package/dist/generated/index.d.ts +0 -3
- package/dist/generated/index.d.ts.map +0 -1
- package/dist/generated/index.js +0 -84
- package/dist/generated/index.js.map +0 -1
- package/dist/generated/sdk.gen.d.ts +0 -966
- package/dist/generated/sdk.gen.d.ts.map +0 -1
- package/dist/generated/sdk.gen.js +0 -1490
- package/dist/generated/sdk.gen.js.map +0 -1
- package/dist/generated/types.gen.d.ts +0 -5646
- package/dist/generated/types.gen.d.ts.map +0 -1
- package/dist/generated/types.gen.js +0 -4
- package/dist/generated/types.gen.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/resources/companies.d.ts +0 -75
- package/dist/resources/companies.d.ts.map +0 -1
- package/dist/resources/companies.js +0 -77
- package/dist/resources/companies.js.map +0 -1
- package/dist/resources/config.d.ts +0 -106
- package/dist/resources/config.d.ts.map +0 -1
- package/dist/resources/config.js +0 -86
- package/dist/resources/config.js.map +0 -1
- package/dist/resources/customers.d.ts +0 -172
- package/dist/resources/customers.d.ts.map +0 -1
- package/dist/resources/customers.js +0 -96
- package/dist/resources/customers.js.map +0 -1
- package/dist/resources/invoices.d.ts +0 -370
- package/dist/resources/invoices.d.ts.map +0 -1
- package/dist/resources/invoices.js +0 -174
- package/dist/resources/invoices.js.map +0 -1
- package/dist/resources/products.d.ts +0 -155
- package/dist/resources/products.d.ts.map +0 -1
- package/dist/resources/products.js +0 -96
- package/dist/resources/products.js.map +0 -1
- package/dist/resources/series.d.ts +0 -98
- package/dist/resources/series.d.ts.map +0 -1
- package/dist/resources/series.js +0 -83
- package/dist/resources/series.js.map +0 -1
- package/dist/webhooks/index.d.ts +0 -20
- package/dist/webhooks/index.d.ts.map +0 -1
- package/dist/webhooks/index.js +0 -70
- package/dist/webhooks/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,52 +1,1558 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
AccountCompaniesResource: () => AccountCompaniesResource,
|
|
34
|
+
AccountInvitationsResource: () => AccountInvitationsResource,
|
|
35
|
+
AccountMembersResource: () => AccountMembersResource,
|
|
36
|
+
AccountScope: () => AccountScope,
|
|
37
|
+
AccountWebhooksResource: () => AccountWebhooksResource,
|
|
38
|
+
AccountsResource: () => AccountsResource,
|
|
39
|
+
BeeL: () => BeeL,
|
|
40
|
+
BeeLApiError: () => BeeLApiError,
|
|
41
|
+
BeeLAuthError: () => BeeLAuthError,
|
|
42
|
+
BeeLConflictError: () => BeeLConflictError,
|
|
43
|
+
BeeLNotFoundError: () => BeeLNotFoundError,
|
|
44
|
+
BeeLRateLimitError: () => BeeLRateLimitError,
|
|
45
|
+
BeeLValidationError: () => BeeLValidationError,
|
|
46
|
+
CompanyCustomersResource: () => CompanyCustomersResource,
|
|
47
|
+
CompanyInvoicesResource: () => CompanyInvoicesResource,
|
|
48
|
+
CompanyProductsResource: () => CompanyProductsResource,
|
|
49
|
+
CompanyRecurringInvoicesResource: () => CompanyRecurringInvoicesResource,
|
|
50
|
+
CompanyScope: () => CompanyScope,
|
|
51
|
+
CompanySeriesResource: () => CompanySeriesResource,
|
|
52
|
+
CustomerBuilder: () => CustomerBuilder,
|
|
53
|
+
InvoiceBuilder: () => InvoiceBuilder,
|
|
54
|
+
VeriFactuSubmissionStatus: () => VeriFactuSubmissionStatus,
|
|
55
|
+
WebhookEventType: () => WebhookEventType,
|
|
56
|
+
WebhookVerificationError: () => WebhookVerificationError,
|
|
57
|
+
WebhookVerifier: () => WebhookVerifier
|
|
58
|
+
});
|
|
59
|
+
module.exports = __toCommonJS(index_exports);
|
|
60
|
+
|
|
61
|
+
// src/http/client.ts
|
|
62
|
+
var import_openapi_fetch = __toESM(require("openapi-fetch"));
|
|
63
|
+
|
|
64
|
+
// src/http/middleware.ts
|
|
65
|
+
var import_crypto = require("crypto");
|
|
66
|
+
|
|
67
|
+
// src/core/errors.ts
|
|
68
|
+
var BeeLApiError = class extends Error {
|
|
69
|
+
constructor(message, statusCode, code, details, requestId) {
|
|
70
|
+
super(message);
|
|
71
|
+
this.name = "BeeLApiError";
|
|
72
|
+
this.statusCode = statusCode;
|
|
73
|
+
this.code = code;
|
|
74
|
+
this.details = details;
|
|
75
|
+
this.requestId = requestId;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var BeeLRateLimitError = class extends BeeLApiError {
|
|
79
|
+
constructor(message, retryAfterSeconds, requestId) {
|
|
80
|
+
super(message, 429, "RATE_LIMIT_EXCEEDED", void 0, requestId);
|
|
81
|
+
this.name = "BeeLRateLimitError";
|
|
82
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var BeeLValidationError = class extends BeeLApiError {
|
|
86
|
+
constructor(message, details, requestId) {
|
|
87
|
+
super(message, 422, "UNPROCESSABLE_ENTITY", details, requestId);
|
|
88
|
+
this.name = "BeeLValidationError";
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var BeeLAuthError = class extends BeeLApiError {
|
|
92
|
+
constructor(message, statusCode, requestId) {
|
|
93
|
+
super(
|
|
94
|
+
message,
|
|
95
|
+
statusCode,
|
|
96
|
+
statusCode === 401 ? "UNAUTHORIZED" : "FORBIDDEN",
|
|
97
|
+
void 0,
|
|
98
|
+
requestId
|
|
99
|
+
);
|
|
100
|
+
this.name = "BeeLAuthError";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var BeeLNotFoundError = class extends BeeLApiError {
|
|
104
|
+
constructor(message, requestId) {
|
|
105
|
+
super(message, 404, "NOT_FOUND", void 0, requestId);
|
|
106
|
+
this.name = "BeeLNotFoundError";
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var BeeLConflictError = class extends BeeLApiError {
|
|
110
|
+
constructor(message, requestId) {
|
|
111
|
+
super(message, 409, "CONFLICT", void 0, requestId);
|
|
112
|
+
this.name = "BeeLConflictError";
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
function throwApiError(status, body) {
|
|
116
|
+
const parsed = body;
|
|
117
|
+
const errorData = parsed?.error ?? parsed;
|
|
118
|
+
const message = errorData?.message ?? `API error ${status}`;
|
|
119
|
+
const code = errorData?.code ?? "UNKNOWN";
|
|
120
|
+
const details = errorData?.details;
|
|
121
|
+
const requestId = parsed?.meta?.request_id;
|
|
122
|
+
switch (status) {
|
|
123
|
+
case 401:
|
|
124
|
+
case 403:
|
|
125
|
+
throw new BeeLAuthError(message, status, requestId);
|
|
126
|
+
case 404:
|
|
127
|
+
throw new BeeLNotFoundError(message, requestId);
|
|
128
|
+
case 409:
|
|
129
|
+
throw new BeeLConflictError(message, requestId);
|
|
130
|
+
case 422:
|
|
131
|
+
throw new BeeLValidationError(message, details, requestId);
|
|
132
|
+
case 429: {
|
|
133
|
+
const retryAfter = errorData?.retry_after ?? 60;
|
|
134
|
+
throw new BeeLRateLimitError(message, retryAfter, requestId);
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
throw new BeeLApiError(message, status, code, details, requestId);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/http/middleware.ts
|
|
142
|
+
var requestMiddleware = {
|
|
143
|
+
async onRequest({ request }) {
|
|
144
|
+
const method = request.method;
|
|
145
|
+
if (["POST", "PUT", "PATCH"].includes(method)) {
|
|
146
|
+
const hasBody = request.headers.get("content-type")?.includes("application/json");
|
|
147
|
+
if (!hasBody) {
|
|
148
|
+
const clone = new Request(request, {
|
|
149
|
+
body: request.body ?? "{}",
|
|
150
|
+
headers: new Headers(request.headers)
|
|
151
|
+
});
|
|
152
|
+
clone.headers.set("Content-Type", "application/json");
|
|
153
|
+
if (method === "POST" && !clone.headers.has("Idempotency-Key")) {
|
|
154
|
+
clone.headers.set("Idempotency-Key", (0, import_crypto.randomUUID)());
|
|
155
|
+
}
|
|
156
|
+
return clone;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (method === "POST" && !request.headers.has("Idempotency-Key")) {
|
|
160
|
+
request.headers.set("Idempotency-Key", (0, import_crypto.randomUUID)());
|
|
161
|
+
}
|
|
162
|
+
return request;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
var errorMiddleware = {
|
|
166
|
+
async onResponse({ response }) {
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
const body = await response.json().catch(() => null);
|
|
169
|
+
throwApiError(response.status, body);
|
|
170
|
+
}
|
|
171
|
+
return response;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
function createRetryMiddleware(options) {
|
|
175
|
+
return {
|
|
176
|
+
async onError({ error, request }) {
|
|
177
|
+
if (!(error instanceof BeeLApiError)) return;
|
|
178
|
+
if (!(error instanceof BeeLRateLimitError) && error.statusCode < 500) return;
|
|
179
|
+
for (let attempt = 0; attempt < options.maxRetries; attempt++) {
|
|
180
|
+
const delay = error instanceof BeeLRateLimitError ? error.retryAfterSeconds * 1e3 : Math.min(
|
|
181
|
+
options.initialDelayMs * Math.pow(2, attempt) + Math.random() * options.initialDelayMs,
|
|
182
|
+
options.maxDelayMs
|
|
183
|
+
);
|
|
184
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
185
|
+
try {
|
|
186
|
+
if (request.method === "POST") {
|
|
187
|
+
request.headers.set("Idempotency-Key", (0, import_crypto.randomUUID)());
|
|
188
|
+
}
|
|
189
|
+
const response = await fetch(request.clone());
|
|
190
|
+
if (response.ok) return response;
|
|
191
|
+
const body = await response.json().catch(() => null);
|
|
192
|
+
throwApiError(response.status, body);
|
|
193
|
+
} catch (retryError) {
|
|
194
|
+
if (!(retryError instanceof BeeLApiError)) throw retryError;
|
|
195
|
+
if (!(retryError instanceof BeeLRateLimitError) && retryError.statusCode < 500) throw retryError;
|
|
196
|
+
if (attempt === options.maxRetries - 1) throw retryError;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/http/client.ts
|
|
204
|
+
function createBeeLClient(config) {
|
|
205
|
+
const client = (0, import_openapi_fetch.default)({
|
|
206
|
+
baseUrl: config.baseUrl ?? "https://app.beel.es/api",
|
|
207
|
+
headers: {
|
|
208
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
client.use(requestMiddleware);
|
|
212
|
+
client.use(errorMiddleware);
|
|
213
|
+
client.use(
|
|
214
|
+
createRetryMiddleware({
|
|
215
|
+
maxRetries: config.maxRetries ?? 3,
|
|
216
|
+
initialDelayMs: config.retryDelayMs ?? 500,
|
|
217
|
+
maxDelayMs: config.maxRetryDelayMs ?? 3e4
|
|
218
|
+
})
|
|
219
|
+
);
|
|
220
|
+
return client;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/resources/invoices.ts
|
|
224
|
+
var InvoicesResource = class {
|
|
225
|
+
constructor(client) {
|
|
226
|
+
this.client = client;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* List invoices with optional filters and pagination.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* const { invoices, pagination } = await beel.invoices.list({ status: 'ISSUED', limit: 20 });
|
|
233
|
+
*/
|
|
234
|
+
async list(params) {
|
|
235
|
+
const { data } = await this.client.GET("/v1/invoices", { params: { query: params } });
|
|
236
|
+
return data.data;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Create a new invoice. An idempotency key is automatically added.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* const invoice = await beel.invoices.create({
|
|
243
|
+
* type: 'STANDARD',
|
|
244
|
+
* recipient: { customer_id: 'uuid' },
|
|
245
|
+
* lines: [{ description: 'Service', quantity: 1, unit_price: 100, discount_percentage: 0 }],
|
|
246
|
+
* });
|
|
247
|
+
*/
|
|
248
|
+
async create(body) {
|
|
249
|
+
const { data } = await this.client.POST("/v1/invoices", { body });
|
|
250
|
+
return data.data;
|
|
251
|
+
}
|
|
252
|
+
/** Get an invoice by ID. */
|
|
253
|
+
async get(id) {
|
|
254
|
+
const { data } = await this.client.GET("/v1/invoices/{invoice_id}", { params: { path: { invoice_id: id } } });
|
|
255
|
+
return data.data;
|
|
256
|
+
}
|
|
257
|
+
/** Update a draft invoice. Only draft invoices can be updated. */
|
|
258
|
+
async update(id, body) {
|
|
259
|
+
const { data } = await this.client.PUT("/v1/invoices/{invoice_id}", { params: { path: { invoice_id: id } }, body });
|
|
260
|
+
return data.data;
|
|
261
|
+
}
|
|
262
|
+
/** Delete a draft invoice. Only draft invoices can be deleted. */
|
|
263
|
+
async delete(id) {
|
|
264
|
+
await this.client.DELETE("/v1/invoices/{invoice_id}", { params: { path: { invoice_id: id } } });
|
|
265
|
+
}
|
|
266
|
+
/** Duplicate an invoice, optionally into a different series. */
|
|
267
|
+
async duplicate(id, options) {
|
|
268
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/duplicate", { params: { path: { invoice_id: id } }, body: options });
|
|
269
|
+
return data.data;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Issue a draft invoice. Assigns an invoice number and triggers VeriFactu submission.
|
|
273
|
+
* @param options.wait_for_pdf - If true, waits for PDF generation before returning.
|
|
274
|
+
*/
|
|
275
|
+
async issue(id, options) {
|
|
276
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/issue", { params: { path: { invoice_id: id }, query: options } });
|
|
277
|
+
return data.data;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Mark an invoice as paid.
|
|
281
|
+
* @param options.payment_date - Payment date (defaults to today).
|
|
282
|
+
* @param options.payment_method - Payment method details.
|
|
283
|
+
*/
|
|
284
|
+
async markPaid(id, options) {
|
|
285
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/mark-paid", { params: { path: { invoice_id: id } }, body: options });
|
|
286
|
+
return data.data;
|
|
287
|
+
}
|
|
288
|
+
/** Mark an invoice as sent (e.g. delivered by other means). */
|
|
289
|
+
async markSent(id, options) {
|
|
290
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/mark-sent", { params: { path: { invoice_id: id } }, body: options });
|
|
291
|
+
return data.data;
|
|
292
|
+
}
|
|
293
|
+
/** Revert a paid/sent invoice back to issued status. */
|
|
294
|
+
async revertToIssued(id) {
|
|
295
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/revert-to-issued", { params: { path: { invoice_id: id } } });
|
|
296
|
+
return data.data;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Void an issued invoice. Requires a reason (min 10 chars).
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* await beel.invoices.void('id', { reason: 'Duplicate invoice sent in error' });
|
|
303
|
+
*/
|
|
304
|
+
async void(id, params) {
|
|
305
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/void", { params: { path: { invoice_id: id } }, body: params });
|
|
306
|
+
return data.data;
|
|
307
|
+
}
|
|
308
|
+
/** Create a corrective invoice that references the original. */
|
|
309
|
+
async createCorrective(id, body) {
|
|
310
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/corrective", { params: { path: { invoice_id: id } }, body });
|
|
311
|
+
return data.data;
|
|
312
|
+
}
|
|
313
|
+
/** Schedule a draft invoice to be issued on a future date. */
|
|
314
|
+
async schedule(id, params) {
|
|
315
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/schedule", { params: { path: { invoice_id: id } }, body: params });
|
|
316
|
+
return data.data;
|
|
317
|
+
}
|
|
318
|
+
/** Cancel a scheduled invoice, returning it to draft. */
|
|
319
|
+
async unschedule(id) {
|
|
320
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/unschedule", { params: { path: { invoice_id: id } } });
|
|
321
|
+
return data.data;
|
|
322
|
+
}
|
|
323
|
+
/** Change the scheduled date of a scheduled invoice. */
|
|
324
|
+
async reschedule(id, params) {
|
|
325
|
+
const { data } = await this.client.PATCH("/v1/invoices/{invoice_id}/reschedule", { params: { path: { invoice_id: id } }, body: params });
|
|
326
|
+
return data.data;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get a pre-signed URL to download the invoice PDF.
|
|
330
|
+
* The URL expires in 5 minutes. Use `beel.downloadPdf(id)` for a simpler Buffer download.
|
|
331
|
+
*/
|
|
332
|
+
async getPdf(id) {
|
|
333
|
+
const { data } = await this.client.GET("/v1/invoices/{invoice_id}/pdf", { params: { path: { invoice_id: id } } });
|
|
334
|
+
return data.data;
|
|
335
|
+
}
|
|
336
|
+
/** Send an invoice by email. Uses the customer's email by default. */
|
|
337
|
+
async sendEmail(id, options) {
|
|
338
|
+
const { data } = await this.client.POST("/v1/invoices/{invoice_id}/send", { params: { path: { invoice_id: id } }, body: options });
|
|
339
|
+
return data.data;
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/resources/customers.ts
|
|
344
|
+
var CustomersResource = class {
|
|
345
|
+
constructor(client) {
|
|
346
|
+
this.client = client;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* List customers with optional filters and pagination.
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* const { customers, pagination } = await beel.customers.list({ search: 'Acme', limit: 10 });
|
|
353
|
+
*/
|
|
354
|
+
async list(params) {
|
|
355
|
+
const { data } = await this.client.GET("/v1/customers", { params: { query: params } });
|
|
356
|
+
return data.data;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Create a new customer.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* const customer = await beel.customers.create({
|
|
363
|
+
* legal_name: 'Acme SL',
|
|
364
|
+
* nif: 'B12345678',
|
|
365
|
+
* address: { street: 'Calle Mayor', number: '1', postal_code: '28001', city: 'Madrid', province: 'Madrid', country: 'Spain', country_code: 'ES' },
|
|
366
|
+
* });
|
|
367
|
+
*/
|
|
368
|
+
async create(body) {
|
|
369
|
+
const { data } = await this.client.POST("/v1/customers", { body });
|
|
370
|
+
return data.data;
|
|
371
|
+
}
|
|
372
|
+
/** Get a customer by ID. */
|
|
373
|
+
async get(id) {
|
|
374
|
+
const { data } = await this.client.GET("/v1/customers/{customer_id}", { params: { path: { customer_id: id } } });
|
|
375
|
+
return data.data;
|
|
376
|
+
}
|
|
377
|
+
/** Update a customer. Only provided fields are changed. */
|
|
378
|
+
async update(id, body) {
|
|
379
|
+
const { data } = await this.client.PUT("/v1/customers/{customer_id}", { params: { path: { customer_id: id } }, body });
|
|
380
|
+
return data.data;
|
|
381
|
+
}
|
|
382
|
+
/** Deactivate (soft-delete) a customer. */
|
|
383
|
+
async deactivate(id) {
|
|
384
|
+
await this.client.DELETE("/v1/customers/{customer_id}", { params: { path: { customer_id: id } } });
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// src/resources/products.ts
|
|
389
|
+
var ProductsResource = class {
|
|
390
|
+
constructor(client) {
|
|
391
|
+
this.client = client;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* List products with optional filters and pagination.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* const { products, pagination } = await beel.products.list({ category: 'SERVICE' });
|
|
398
|
+
*/
|
|
399
|
+
async list(params) {
|
|
400
|
+
const { data } = await this.client.GET("/v1/products", { params: { query: params } });
|
|
401
|
+
return data.data;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Create a new product or service.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* const product = await beel.products.create({
|
|
408
|
+
* name: 'Consulting',
|
|
409
|
+
* code: 'CONS-001',
|
|
410
|
+
* category: 'SERVICE',
|
|
411
|
+
* default_price: 100,
|
|
412
|
+
* main_tax: { type: 'IVA', percentage: 21 },
|
|
413
|
+
* });
|
|
414
|
+
*/
|
|
415
|
+
async create(body) {
|
|
416
|
+
const { data } = await this.client.POST("/v1/products", { body });
|
|
417
|
+
return data.data;
|
|
418
|
+
}
|
|
419
|
+
/** Get a product by ID. */
|
|
420
|
+
async get(id) {
|
|
421
|
+
const { data } = await this.client.GET("/v1/products/{product_id}", { params: { path: { product_id: id } } });
|
|
422
|
+
return data.data;
|
|
423
|
+
}
|
|
424
|
+
/** Update a product. Only provided fields are changed. */
|
|
425
|
+
async update(id, body) {
|
|
426
|
+
const { data } = await this.client.PUT("/v1/products/{product_id}", { params: { path: { product_id: id } }, body });
|
|
427
|
+
return data.data;
|
|
428
|
+
}
|
|
429
|
+
/** Delete a product permanently. */
|
|
430
|
+
async delete(id) {
|
|
431
|
+
await this.client.DELETE("/v1/products/{product_id}", { params: { path: { product_id: id } } });
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Search products by name or code. Returns up to `limit` results.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* const results = await beel.products.search('consulting', 5);
|
|
438
|
+
*/
|
|
439
|
+
async search(q, limit) {
|
|
440
|
+
const { data } = await this.client.GET("/v1/products/search", { params: { query: { q, limit } } });
|
|
441
|
+
return data.data;
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// src/resources/configuration.ts
|
|
446
|
+
var ConfigurationResource = class {
|
|
447
|
+
constructor(client) {
|
|
448
|
+
this.client = client;
|
|
449
|
+
}
|
|
450
|
+
/** Get the current tax configuration (default VAT, IRPF, etc.). */
|
|
451
|
+
async getTaxConfig() {
|
|
452
|
+
const { data } = await this.client.GET("/v1/configuration/taxes");
|
|
453
|
+
return data.data;
|
|
454
|
+
}
|
|
455
|
+
/** Update tax configuration. */
|
|
456
|
+
async updateTaxConfig(body) {
|
|
457
|
+
const { data } = await this.client.PUT("/v1/configuration/taxes", { body });
|
|
458
|
+
return data.data;
|
|
459
|
+
}
|
|
460
|
+
/** Get available tax types (IVA/IGIC rates, IRPF types, equivalence surcharges). */
|
|
461
|
+
async getTaxTypes() {
|
|
462
|
+
const { data } = await this.client.GET("/v1/configuration/tax-types");
|
|
463
|
+
return data.data;
|
|
464
|
+
}
|
|
465
|
+
/** Get invoice customization options (logo, colors, footer text, etc.). */
|
|
466
|
+
async getInvoiceCustomizationOptions() {
|
|
467
|
+
const { data } = await this.client.GET("/v1/configuration/invoice-customization-options");
|
|
468
|
+
return data.data;
|
|
469
|
+
}
|
|
470
|
+
/** Update the user's preferred language (es, en, ca). */
|
|
471
|
+
async updateLanguage(language) {
|
|
472
|
+
const { data } = await this.client.PUT("/v1/configuration/language", { body: { language } });
|
|
473
|
+
return data.data;
|
|
474
|
+
}
|
|
475
|
+
/** Get VeriFactu configuration (enabled, certificate status, etc.). */
|
|
476
|
+
async getVerifactu() {
|
|
477
|
+
const { data } = await this.client.GET("/v1/configuration/verifactu");
|
|
478
|
+
return data.data;
|
|
479
|
+
}
|
|
480
|
+
/** Update VeriFactu configuration. */
|
|
481
|
+
async updateVerifactu(body) {
|
|
482
|
+
const { data } = await this.client.PUT("/v1/configuration/verifactu", { body });
|
|
483
|
+
return data.data;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// src/resources/series.ts
|
|
488
|
+
var SeriesResource = class {
|
|
489
|
+
constructor(client) {
|
|
490
|
+
this.client = client;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* List all invoice series. Optionally filter by active status.
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* const series = await beel.series.list();
|
|
497
|
+
* const activeSeries = await beel.series.list(true);
|
|
498
|
+
*/
|
|
499
|
+
async list(active) {
|
|
500
|
+
const { data } = await this.client.GET("/v1/configuration/series", {
|
|
501
|
+
params: { query: active !== void 0 ? { active } : void 0 }
|
|
502
|
+
});
|
|
503
|
+
return data.data;
|
|
504
|
+
}
|
|
505
|
+
/** Create a new invoice series (e.g. "A-2026", "RECT"). */
|
|
506
|
+
async create(body) {
|
|
507
|
+
const { data } = await this.client.POST("/v1/configuration/series", { body });
|
|
508
|
+
return data.data;
|
|
509
|
+
}
|
|
510
|
+
/** Update a series (name, description, etc.). */
|
|
511
|
+
async update(id, body) {
|
|
512
|
+
const { data } = await this.client.PUT("/v1/configuration/series/{series_id}", {
|
|
513
|
+
params: { path: { series_id: id } },
|
|
514
|
+
body
|
|
515
|
+
});
|
|
516
|
+
return data.data;
|
|
517
|
+
}
|
|
518
|
+
/** Delete an invoice series. Only empty series can be deleted. */
|
|
519
|
+
async delete(id) {
|
|
520
|
+
await this.client.DELETE("/v1/configuration/series/{series_id}", {
|
|
521
|
+
params: { path: { series_id: id } }
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
/** Set a series as the default for new invoices. */
|
|
525
|
+
async setDefault(id) {
|
|
526
|
+
const { data } = await this.client.POST("/v1/configuration/series/{series_id}/default", {
|
|
527
|
+
params: { path: { series_id: id } }
|
|
528
|
+
});
|
|
529
|
+
return data.data;
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// src/resources/nif.ts
|
|
534
|
+
var NifResource = class {
|
|
535
|
+
constructor(client) {
|
|
536
|
+
this.client = client;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Validate a Spanish NIF/CIF against the AEAT tax registry.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* const result = await beel.nif.validate('B12345678');
|
|
543
|
+
* console.log(result.valid, result.name);
|
|
544
|
+
*/
|
|
545
|
+
async validate(nif) {
|
|
546
|
+
const { data } = await this.client.POST("/v1/nif/validate", { body: { nif } });
|
|
547
|
+
return data.data;
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// src/resources/accounts.ts
|
|
552
|
+
var AccountsResource = class {
|
|
553
|
+
constructor(client) {
|
|
554
|
+
this.client = client;
|
|
555
|
+
}
|
|
556
|
+
/** List accounts reachable with this API key (cursor-paginated). */
|
|
557
|
+
async list(params) {
|
|
558
|
+
const { data } = await this.client.GET("/v1/accounts", { params: { query: params } });
|
|
559
|
+
return data.data;
|
|
560
|
+
}
|
|
561
|
+
/** Provision a new managed account. */
|
|
562
|
+
async provision(body) {
|
|
563
|
+
const { data } = await this.client.POST("/v1/accounts", { body });
|
|
564
|
+
return data.data;
|
|
565
|
+
}
|
|
566
|
+
/** Get a managed account by ID. */
|
|
567
|
+
async get(accountId) {
|
|
568
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}", {
|
|
569
|
+
params: { path: { account_id: accountId } }
|
|
570
|
+
});
|
|
571
|
+
return data.data;
|
|
572
|
+
}
|
|
573
|
+
/** Alias of `beel.account(accountId)` — returns an account-scoped facade. */
|
|
574
|
+
scope(accountId) {
|
|
575
|
+
return new AccountScope(this.client, accountId);
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
var AccountScope = class {
|
|
579
|
+
constructor(client, accountId) {
|
|
580
|
+
this.client = client;
|
|
581
|
+
this.accountId = accountId;
|
|
582
|
+
this.members = new AccountMembersResource(client, accountId);
|
|
583
|
+
this.invitations = new AccountInvitationsResource(client, accountId);
|
|
584
|
+
this.webhooks = new AccountWebhooksResource(client, accountId);
|
|
585
|
+
this.companies = new AccountCompaniesResource(client, accountId);
|
|
586
|
+
}
|
|
587
|
+
path() {
|
|
588
|
+
return { account_id: this.accountId };
|
|
589
|
+
}
|
|
590
|
+
/** Get the account summary. */
|
|
591
|
+
async get() {
|
|
592
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}", { params: { path: this.path() } });
|
|
593
|
+
return data.data;
|
|
594
|
+
}
|
|
595
|
+
/** Provisioning usage counters (accounts, NIFs) for billing purposes. */
|
|
596
|
+
async usage() {
|
|
597
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/usage", { params: { path: this.path() } });
|
|
598
|
+
return data.data;
|
|
599
|
+
}
|
|
600
|
+
/** Change the manager's access level over this account. */
|
|
601
|
+
async changeAccessLevel(body) {
|
|
602
|
+
await this.client.PATCH("/v1/accounts/{account_id}/access-level", {
|
|
603
|
+
params: { path: this.path() },
|
|
604
|
+
body
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
/** End the management relationship with this account. */
|
|
608
|
+
async endManagement() {
|
|
609
|
+
await this.client.DELETE("/v1/accounts/{account_id}/management", { params: { path: this.path() } });
|
|
610
|
+
}
|
|
611
|
+
/** Create a claim token so the end user can take ownership of the account. */
|
|
612
|
+
async createClaimToken(body) {
|
|
613
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/claim-tokens", {
|
|
614
|
+
params: { path: this.path() },
|
|
615
|
+
body: body ?? {}
|
|
616
|
+
});
|
|
617
|
+
return data.data;
|
|
618
|
+
}
|
|
619
|
+
/** Transfer account ownership to an existing member. */
|
|
620
|
+
async setOwner(body) {
|
|
621
|
+
await this.client.PUT("/v1/accounts/{account_id}/owner", {
|
|
622
|
+
params: { path: this.path() },
|
|
623
|
+
body
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
var AccountMembersResource = class {
|
|
628
|
+
constructor(client, accountId) {
|
|
629
|
+
this.client = client;
|
|
630
|
+
this.accountId = accountId;
|
|
631
|
+
}
|
|
632
|
+
async list() {
|
|
633
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/members", {
|
|
634
|
+
params: { path: { account_id: this.accountId } }
|
|
635
|
+
});
|
|
636
|
+
return data.data.members;
|
|
637
|
+
}
|
|
638
|
+
async get(memberId) {
|
|
639
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/members/{member_id}", {
|
|
640
|
+
params: { path: { account_id: this.accountId, member_id: memberId } }
|
|
641
|
+
});
|
|
642
|
+
return data.data;
|
|
643
|
+
}
|
|
644
|
+
/** Update a member's account role. */
|
|
645
|
+
async update(memberId, body) {
|
|
646
|
+
const { data } = await this.client.PATCH("/v1/accounts/{account_id}/members/{member_id}", {
|
|
647
|
+
params: { path: { account_id: this.accountId, member_id: memberId } },
|
|
648
|
+
body
|
|
649
|
+
});
|
|
650
|
+
return data.data;
|
|
651
|
+
}
|
|
652
|
+
/** Remove a member from the account. */
|
|
653
|
+
async remove(memberId) {
|
|
654
|
+
await this.client.DELETE("/v1/accounts/{account_id}/members/{member_id}", {
|
|
655
|
+
params: { path: { account_id: this.accountId, member_id: memberId } }
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
/** List a member's per-company grants. */
|
|
659
|
+
async listGrants(memberId) {
|
|
660
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/members/{member_id}/grants", {
|
|
661
|
+
params: { path: { account_id: this.accountId, member_id: memberId } }
|
|
662
|
+
});
|
|
663
|
+
return data.data;
|
|
664
|
+
}
|
|
665
|
+
/** Grant (or replace) a member's permissions over one company. */
|
|
666
|
+
async putGrant(memberId, companyId, body) {
|
|
667
|
+
const { data } = await this.client.PUT("/v1/accounts/{account_id}/members/{member_id}/grants/{company_id}", {
|
|
668
|
+
params: { path: { account_id: this.accountId, member_id: memberId, company_id: companyId } },
|
|
669
|
+
body
|
|
670
|
+
});
|
|
671
|
+
return data.data;
|
|
672
|
+
}
|
|
673
|
+
/** Revoke a member's grant over one company. */
|
|
674
|
+
async removeGrant(memberId, companyId) {
|
|
675
|
+
await this.client.DELETE("/v1/accounts/{account_id}/members/{member_id}/grants/{company_id}", {
|
|
676
|
+
params: { path: { account_id: this.accountId, member_id: memberId, company_id: companyId } }
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
var AccountInvitationsResource = class {
|
|
681
|
+
constructor(client, accountId) {
|
|
682
|
+
this.client = client;
|
|
683
|
+
this.accountId = accountId;
|
|
684
|
+
}
|
|
685
|
+
async list() {
|
|
686
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/invitations", {
|
|
687
|
+
params: { path: { account_id: this.accountId } }
|
|
688
|
+
});
|
|
689
|
+
return data.data;
|
|
690
|
+
}
|
|
691
|
+
async create(body) {
|
|
692
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/invitations", {
|
|
693
|
+
params: { path: { account_id: this.accountId } },
|
|
694
|
+
body
|
|
695
|
+
});
|
|
696
|
+
return data.data;
|
|
697
|
+
}
|
|
698
|
+
async get(invitationId) {
|
|
699
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/invitations/{invitation_id}", {
|
|
700
|
+
params: { path: { account_id: this.accountId, invitation_id: invitationId } }
|
|
701
|
+
});
|
|
702
|
+
return data.data;
|
|
703
|
+
}
|
|
704
|
+
async revoke(invitationId) {
|
|
705
|
+
await this.client.DELETE("/v1/accounts/{account_id}/invitations/{invitation_id}", {
|
|
706
|
+
params: { path: { account_id: this.accountId, invitation_id: invitationId } }
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
var AccountWebhooksResource = class {
|
|
711
|
+
constructor(client, accountId) {
|
|
712
|
+
this.client = client;
|
|
713
|
+
this.accountId = accountId;
|
|
714
|
+
}
|
|
715
|
+
async list(params) {
|
|
716
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/webhooks", {
|
|
717
|
+
params: { path: { account_id: this.accountId }, query: params }
|
|
718
|
+
});
|
|
719
|
+
return data.data;
|
|
720
|
+
}
|
|
721
|
+
async create(body) {
|
|
722
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/webhooks", {
|
|
723
|
+
params: { path: { account_id: this.accountId } },
|
|
724
|
+
body
|
|
725
|
+
});
|
|
726
|
+
return data.data;
|
|
727
|
+
}
|
|
728
|
+
async get(webhookId) {
|
|
729
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/webhooks/{webhook_id}", {
|
|
730
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId } }
|
|
731
|
+
});
|
|
732
|
+
return data.data;
|
|
733
|
+
}
|
|
734
|
+
async update(webhookId, body) {
|
|
735
|
+
const { data } = await this.client.PATCH("/v1/accounts/{account_id}/webhooks/{webhook_id}", {
|
|
736
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId } },
|
|
737
|
+
body
|
|
738
|
+
});
|
|
739
|
+
return data.data;
|
|
740
|
+
}
|
|
741
|
+
async delete(webhookId) {
|
|
742
|
+
await this.client.DELETE("/v1/accounts/{account_id}/webhooks/{webhook_id}", {
|
|
743
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId } }
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
/** Send a test event to the webhook endpoint. */
|
|
747
|
+
async test(webhookId) {
|
|
748
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/webhooks/{webhook_id}/test", {
|
|
749
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId } }
|
|
750
|
+
});
|
|
751
|
+
return data.data;
|
|
752
|
+
}
|
|
753
|
+
/** Rotate the webhook signing secret. */
|
|
754
|
+
async rotateSecret(webhookId) {
|
|
755
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/webhooks/{webhook_id}/secret", {
|
|
756
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId } }
|
|
757
|
+
});
|
|
758
|
+
return data.data;
|
|
759
|
+
}
|
|
760
|
+
async listDeliveries(webhookId, params) {
|
|
761
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/webhooks/{webhook_id}/deliveries", {
|
|
762
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId }, query: params }
|
|
763
|
+
});
|
|
764
|
+
return data.data;
|
|
765
|
+
}
|
|
766
|
+
async retryDelivery(webhookId, deliveryId) {
|
|
767
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry", {
|
|
768
|
+
params: { path: { account_id: this.accountId, webhook_id: webhookId, delivery_id: deliveryId } }
|
|
769
|
+
});
|
|
770
|
+
return data.data;
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
var AccountCompaniesResource = class {
|
|
774
|
+
constructor(client, accountId) {
|
|
775
|
+
this.client = client;
|
|
776
|
+
this.accountId = accountId;
|
|
777
|
+
}
|
|
778
|
+
async list(params) {
|
|
779
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/companies", {
|
|
780
|
+
params: { path: { account_id: this.accountId }, query: params }
|
|
781
|
+
});
|
|
782
|
+
return { companies: data.data ?? [], pagination: data.pagination };
|
|
783
|
+
}
|
|
784
|
+
/** Register a new company (NIF) under the account. */
|
|
785
|
+
async create(body) {
|
|
786
|
+
const { data } = await this.client.POST("/v1/accounts/{account_id}/companies", {
|
|
787
|
+
params: { path: { account_id: this.accountId } },
|
|
788
|
+
body
|
|
789
|
+
});
|
|
790
|
+
return data.data;
|
|
791
|
+
}
|
|
792
|
+
/** Aggregated per-company stats for the account. */
|
|
793
|
+
async stats() {
|
|
794
|
+
const { data } = await this.client.GET("/v1/accounts/{account_id}/companies/stats", {
|
|
795
|
+
params: { path: { account_id: this.accountId } }
|
|
796
|
+
});
|
|
797
|
+
return data.data;
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
// src/resources/company.ts
|
|
802
|
+
var CompanyScope = class {
|
|
803
|
+
constructor(client, companyId) {
|
|
804
|
+
this.client = client;
|
|
805
|
+
this.companyId = companyId;
|
|
806
|
+
this.invoices = new CompanyInvoicesResource(client, companyId);
|
|
807
|
+
this.customers = new CompanyCustomersResource(client, companyId);
|
|
808
|
+
this.products = new CompanyProductsResource(client, companyId);
|
|
809
|
+
this.series = new CompanySeriesResource(client, companyId);
|
|
810
|
+
this.recurringInvoices = new CompanyRecurringInvoicesResource(client, companyId);
|
|
811
|
+
}
|
|
812
|
+
path() {
|
|
813
|
+
return { company_id: this.companyId };
|
|
814
|
+
}
|
|
815
|
+
/** Get the company. */
|
|
816
|
+
async get(params) {
|
|
817
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}", {
|
|
818
|
+
params: { path: this.path(), query: params }
|
|
819
|
+
});
|
|
820
|
+
return data.data;
|
|
821
|
+
}
|
|
822
|
+
/** Update company data. */
|
|
823
|
+
async update(body) {
|
|
824
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}", {
|
|
825
|
+
params: { path: this.path() },
|
|
826
|
+
body
|
|
827
|
+
});
|
|
828
|
+
return data.data;
|
|
829
|
+
}
|
|
830
|
+
/** Delete the company. */
|
|
831
|
+
async delete() {
|
|
832
|
+
await this.client.DELETE("/v1/companies/{company_id}", { params: { path: this.path() } });
|
|
833
|
+
}
|
|
834
|
+
/** Fiscal summary (VAT/IRPF aggregates) for the company. */
|
|
835
|
+
async fiscalSummary(params) {
|
|
836
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/fiscal-summary", {
|
|
837
|
+
params: { path: this.path(), query: params }
|
|
838
|
+
});
|
|
839
|
+
return data.data;
|
|
840
|
+
}
|
|
841
|
+
/** Whether the company can already issue invoices, and what is missing if not. */
|
|
842
|
+
async issuingReadiness() {
|
|
843
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/issuing-readiness", {
|
|
844
|
+
params: { path: this.path() }
|
|
845
|
+
});
|
|
846
|
+
return data.data;
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
var CompanyInvoicesResource = class {
|
|
850
|
+
constructor(client, companyId) {
|
|
851
|
+
this.client = client;
|
|
852
|
+
this.companyId = companyId;
|
|
853
|
+
}
|
|
854
|
+
path(rest) {
|
|
855
|
+
return { company_id: this.companyId, ...rest };
|
|
856
|
+
}
|
|
857
|
+
async list(params) {
|
|
858
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/invoices", {
|
|
859
|
+
params: { path: this.path(), query: params }
|
|
860
|
+
});
|
|
861
|
+
return data.data;
|
|
862
|
+
}
|
|
863
|
+
async create(body, params) {
|
|
864
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices", {
|
|
865
|
+
params: { path: this.path(), query: params },
|
|
866
|
+
body
|
|
867
|
+
});
|
|
868
|
+
return data.data;
|
|
869
|
+
}
|
|
870
|
+
async get(invoiceId) {
|
|
871
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/invoices/{invoice_id}", {
|
|
872
|
+
params: { path: this.path({ invoice_id: invoiceId }) }
|
|
873
|
+
});
|
|
874
|
+
return data.data;
|
|
875
|
+
}
|
|
876
|
+
/** Update a draft invoice. */
|
|
877
|
+
async update(invoiceId, body) {
|
|
878
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}/invoices/{invoice_id}", {
|
|
879
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
880
|
+
body
|
|
881
|
+
});
|
|
882
|
+
return data.data;
|
|
883
|
+
}
|
|
884
|
+
/** Delete a draft invoice. */
|
|
885
|
+
async delete(invoiceId) {
|
|
886
|
+
await this.client.DELETE("/v1/companies/{company_id}/invoices/{invoice_id}", {
|
|
887
|
+
params: { path: this.path({ invoice_id: invoiceId }) }
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
/** Issue a draft invoice (assigns number, submits to VeriFactu when configured). */
|
|
891
|
+
async issue(invoiceId, params) {
|
|
892
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices/{invoice_id}/issue", {
|
|
893
|
+
params: { path: this.path({ invoice_id: invoiceId }), query: params }
|
|
894
|
+
});
|
|
895
|
+
return data.data;
|
|
896
|
+
}
|
|
897
|
+
/** Void an issued invoice. */
|
|
898
|
+
async void(invoiceId, body) {
|
|
899
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices/{invoice_id}/void", {
|
|
900
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
901
|
+
body
|
|
902
|
+
});
|
|
903
|
+
return data.data;
|
|
904
|
+
}
|
|
905
|
+
/** Create a corrective (rectificativa) for an issued invoice. */
|
|
906
|
+
async createCorrective(invoiceId, body) {
|
|
907
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices/{invoice_id}/corrective", {
|
|
908
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
909
|
+
body
|
|
910
|
+
});
|
|
911
|
+
return data.data;
|
|
912
|
+
}
|
|
913
|
+
/** Convert a proforma into an invoice. */
|
|
914
|
+
async convertToInvoice(invoiceId, body) {
|
|
915
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices/{invoice_id}/convert-to-invoice", {
|
|
916
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
917
|
+
body
|
|
918
|
+
});
|
|
919
|
+
return data.data;
|
|
920
|
+
}
|
|
921
|
+
/** Update payment status (e.g. mark as paid). */
|
|
922
|
+
async setStatus(invoiceId, body) {
|
|
923
|
+
const { data } = await this.client.PUT("/v1/companies/{company_id}/invoices/{invoice_id}/status", {
|
|
924
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
925
|
+
body
|
|
926
|
+
});
|
|
927
|
+
return data.data;
|
|
928
|
+
}
|
|
929
|
+
/** Get PDF metadata and download URL. */
|
|
930
|
+
async getPdf(invoiceId) {
|
|
931
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/invoices/{invoice_id}/pdf", {
|
|
932
|
+
params: { path: this.path({ invoice_id: invoiceId }) }
|
|
933
|
+
});
|
|
934
|
+
return data.data;
|
|
935
|
+
}
|
|
936
|
+
/** Send the invoice by email to the customer. */
|
|
937
|
+
async send(invoiceId, body) {
|
|
938
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/invoices/{invoice_id}/send", {
|
|
939
|
+
params: { path: this.path({ invoice_id: invoiceId }) },
|
|
940
|
+
body
|
|
941
|
+
});
|
|
942
|
+
return data.data;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
var CompanyCustomersResource = class {
|
|
946
|
+
constructor(client, companyId) {
|
|
947
|
+
this.client = client;
|
|
948
|
+
this.companyId = companyId;
|
|
949
|
+
}
|
|
950
|
+
async list(params) {
|
|
951
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/customers", {
|
|
952
|
+
params: { path: { company_id: this.companyId }, query: params }
|
|
953
|
+
});
|
|
954
|
+
return data.data;
|
|
955
|
+
}
|
|
956
|
+
async create(body) {
|
|
957
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/customers", {
|
|
958
|
+
params: { path: { company_id: this.companyId } },
|
|
959
|
+
body
|
|
960
|
+
});
|
|
961
|
+
return data.data;
|
|
962
|
+
}
|
|
963
|
+
async createBulk(body) {
|
|
964
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/customers/bulk", {
|
|
965
|
+
params: { path: { company_id: this.companyId } },
|
|
966
|
+
body
|
|
967
|
+
});
|
|
968
|
+
return data.data;
|
|
969
|
+
}
|
|
970
|
+
async get(customerId) {
|
|
971
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/customers/{customer_id}", {
|
|
972
|
+
params: { path: { company_id: this.companyId, customer_id: customerId } }
|
|
973
|
+
});
|
|
974
|
+
return data.data;
|
|
975
|
+
}
|
|
976
|
+
async update(customerId, body) {
|
|
977
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}/customers/{customer_id}", {
|
|
978
|
+
params: { path: { company_id: this.companyId, customer_id: customerId } },
|
|
979
|
+
body
|
|
980
|
+
});
|
|
981
|
+
return data.data;
|
|
982
|
+
}
|
|
983
|
+
async delete(customerId) {
|
|
984
|
+
await this.client.DELETE("/v1/companies/{company_id}/customers/{customer_id}", {
|
|
985
|
+
params: { path: { company_id: this.companyId, customer_id: customerId } }
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
var CompanyProductsResource = class {
|
|
990
|
+
constructor(client, companyId) {
|
|
991
|
+
this.client = client;
|
|
992
|
+
this.companyId = companyId;
|
|
993
|
+
}
|
|
994
|
+
async list(params) {
|
|
995
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/products", {
|
|
996
|
+
params: { path: { company_id: this.companyId }, query: params }
|
|
997
|
+
});
|
|
998
|
+
return data.data;
|
|
999
|
+
}
|
|
1000
|
+
async create(body) {
|
|
1001
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/products", {
|
|
1002
|
+
params: { path: { company_id: this.companyId } },
|
|
1003
|
+
body
|
|
1004
|
+
});
|
|
1005
|
+
return data.data;
|
|
1006
|
+
}
|
|
1007
|
+
async get(productId) {
|
|
1008
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/products/{product_id}", {
|
|
1009
|
+
params: { path: { company_id: this.companyId, product_id: productId } }
|
|
1010
|
+
});
|
|
1011
|
+
return data.data;
|
|
1012
|
+
}
|
|
1013
|
+
async update(productId, body) {
|
|
1014
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}/products/{product_id}", {
|
|
1015
|
+
params: { path: { company_id: this.companyId, product_id: productId } },
|
|
1016
|
+
body
|
|
1017
|
+
});
|
|
1018
|
+
return data.data;
|
|
1019
|
+
}
|
|
1020
|
+
async delete(productId) {
|
|
1021
|
+
await this.client.DELETE("/v1/companies/{company_id}/products/{product_id}", {
|
|
1022
|
+
params: { path: { company_id: this.companyId, product_id: productId } }
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
var CompanySeriesResource = class {
|
|
1027
|
+
constructor(client, companyId) {
|
|
1028
|
+
this.client = client;
|
|
1029
|
+
this.companyId = companyId;
|
|
1030
|
+
}
|
|
1031
|
+
async list(params) {
|
|
1032
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/series", {
|
|
1033
|
+
params: { path: { company_id: this.companyId }, query: params }
|
|
1034
|
+
});
|
|
1035
|
+
return data.data;
|
|
1036
|
+
}
|
|
1037
|
+
async create(body) {
|
|
1038
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/series", {
|
|
1039
|
+
params: { path: { company_id: this.companyId } },
|
|
1040
|
+
body
|
|
1041
|
+
});
|
|
1042
|
+
return data.data;
|
|
1043
|
+
}
|
|
1044
|
+
async update(seriesId, body) {
|
|
1045
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}/series/{series_id}", {
|
|
1046
|
+
params: { path: { company_id: this.companyId, series_id: seriesId } },
|
|
1047
|
+
body
|
|
1048
|
+
});
|
|
1049
|
+
return data.data;
|
|
1050
|
+
}
|
|
1051
|
+
async delete(seriesId) {
|
|
1052
|
+
await this.client.DELETE("/v1/companies/{company_id}/series/{series_id}", {
|
|
1053
|
+
params: { path: { company_id: this.companyId, series_id: seriesId } }
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
/** Current default series per invoice type. */
|
|
1057
|
+
async getDefaults() {
|
|
1058
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/series/defaults", {
|
|
1059
|
+
params: { path: { company_id: this.companyId } }
|
|
1060
|
+
});
|
|
1061
|
+
return data.data;
|
|
1062
|
+
}
|
|
1063
|
+
/** Ensure the three typed default series exist (idempotent seeding). */
|
|
1064
|
+
async ensureDefaults() {
|
|
1065
|
+
const { data } = await this.client.PUT("/v1/companies/{company_id}/series/defaults", {
|
|
1066
|
+
params: { path: { company_id: this.companyId } }
|
|
1067
|
+
});
|
|
1068
|
+
return data.data;
|
|
1069
|
+
}
|
|
1070
|
+
/** Mark a series as the default for its invoice type. */
|
|
1071
|
+
async setDefault(seriesId) {
|
|
1072
|
+
const { data } = await this.client.PUT("/v1/companies/{company_id}/series/{series_id}/default", {
|
|
1073
|
+
params: { path: { company_id: this.companyId, series_id: seriesId } }
|
|
1074
|
+
});
|
|
1075
|
+
return data.data;
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
var CompanyRecurringInvoicesResource = class {
|
|
1079
|
+
constructor(client, companyId) {
|
|
1080
|
+
this.client = client;
|
|
1081
|
+
this.companyId = companyId;
|
|
1082
|
+
}
|
|
1083
|
+
path(rest) {
|
|
1084
|
+
return { company_id: this.companyId, ...rest };
|
|
1085
|
+
}
|
|
1086
|
+
async list(params) {
|
|
1087
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/recurring-invoices", {
|
|
1088
|
+
params: { path: this.path(), query: params }
|
|
1089
|
+
});
|
|
1090
|
+
return data.data;
|
|
1091
|
+
}
|
|
1092
|
+
async create(body) {
|
|
1093
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/recurring-invoices", {
|
|
1094
|
+
params: { path: this.path() },
|
|
1095
|
+
body
|
|
1096
|
+
});
|
|
1097
|
+
return data.data;
|
|
1098
|
+
}
|
|
1099
|
+
async get(recurringInvoiceId) {
|
|
1100
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}", {
|
|
1101
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) }
|
|
1102
|
+
});
|
|
1103
|
+
return data.data;
|
|
1104
|
+
}
|
|
1105
|
+
async update(recurringInvoiceId, body) {
|
|
1106
|
+
const { data } = await this.client.PATCH("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}", {
|
|
1107
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) },
|
|
1108
|
+
body
|
|
1109
|
+
});
|
|
1110
|
+
return data.data;
|
|
1111
|
+
}
|
|
1112
|
+
async delete(recurringInvoiceId) {
|
|
1113
|
+
await this.client.DELETE("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}", {
|
|
1114
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) }
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
/** Pause or resume the schedule. */
|
|
1118
|
+
async setStatus(recurringInvoiceId, body) {
|
|
1119
|
+
const { data } = await this.client.PUT("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/status", {
|
|
1120
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) },
|
|
1121
|
+
body
|
|
1122
|
+
});
|
|
1123
|
+
return data.data;
|
|
1124
|
+
}
|
|
1125
|
+
/** Skip the next scheduled occurrence. */
|
|
1126
|
+
async skip(recurringInvoiceId) {
|
|
1127
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/skip", {
|
|
1128
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) }
|
|
1129
|
+
});
|
|
1130
|
+
return data.data;
|
|
1131
|
+
}
|
|
1132
|
+
/** Generate the next invoice now instead of waiting for the schedule. */
|
|
1133
|
+
async generateNow(recurringInvoiceId) {
|
|
1134
|
+
const { data } = await this.client.POST("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/generate", {
|
|
1135
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) }
|
|
1136
|
+
});
|
|
1137
|
+
return data.data;
|
|
1138
|
+
}
|
|
1139
|
+
async nextOccurrence(recurringInvoiceId) {
|
|
1140
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/next-occurrence", {
|
|
1141
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }) }
|
|
1142
|
+
});
|
|
1143
|
+
return data.data;
|
|
1144
|
+
}
|
|
1145
|
+
async history(recurringInvoiceId, params) {
|
|
1146
|
+
const { data } = await this.client.GET("/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/history", {
|
|
1147
|
+
params: { path: this.path({ recurring_invoice_id: recurringInvoiceId }), query: params }
|
|
1148
|
+
});
|
|
1149
|
+
return data.data;
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1153
|
+
// src/client.ts
|
|
1154
|
+
var BeeL = class {
|
|
1155
|
+
constructor(config) {
|
|
1156
|
+
const client = createBeeLClient(config);
|
|
1157
|
+
this._client = client;
|
|
1158
|
+
this.invoices = new InvoicesResource(client);
|
|
1159
|
+
this.customers = new CustomersResource(client);
|
|
1160
|
+
this.products = new ProductsResource(client);
|
|
1161
|
+
this.configuration = new ConfigurationResource(client);
|
|
1162
|
+
this.series = new SeriesResource(client);
|
|
1163
|
+
this.nif = new NifResource(client);
|
|
1164
|
+
this.accounts = new AccountsResource(client);
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Returns a facade scoped to one company (NIF) — the explicit multi-NIF surface.
|
|
1168
|
+
* All operations address the company in the path, no session focus needed.
|
|
1169
|
+
*
|
|
1170
|
+
* @example
|
|
1171
|
+
* ```typescript
|
|
1172
|
+
* const company = beel.company('company-uuid');
|
|
1173
|
+
* const { invoices } = await company.invoices.list({ status: 'ISSUED' });
|
|
1174
|
+
* ```
|
|
1175
|
+
*/
|
|
1176
|
+
company(companyId) {
|
|
1177
|
+
return new CompanyScope(this._client, companyId);
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Returns a facade scoped to one managed account — members, invitations,
|
|
1181
|
+
* account webhooks, companies, usage. Symmetric with {@link company}.
|
|
1182
|
+
*
|
|
1183
|
+
* @example
|
|
1184
|
+
* ```typescript
|
|
1185
|
+
* const account = beel.account('account-uuid');
|
|
1186
|
+
* const members = await account.members.list();
|
|
1187
|
+
* ```
|
|
1188
|
+
*/
|
|
1189
|
+
account(accountId) {
|
|
1190
|
+
return new AccountScope(this._client, accountId);
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Download an invoice PDF as a Buffer.
|
|
1194
|
+
*
|
|
1195
|
+
* @deprecated Relies on the deprecated session-focus PDF endpoint. Use
|
|
1196
|
+
* `beel.company(companyId).invoices.getPdf(invoiceId)` and fetch `download_url` instead.
|
|
1197
|
+
*
|
|
1198
|
+
* @example
|
|
1199
|
+
* ```typescript
|
|
1200
|
+
* const { buffer, fileName } = await beel.downloadPdf('invoice-uuid');
|
|
1201
|
+
* fs.writeFileSync(fileName, buffer);
|
|
1202
|
+
* ```
|
|
1203
|
+
*/
|
|
1204
|
+
async downloadPdf(invoiceId) {
|
|
1205
|
+
const pdf = await this.invoices.getPdf(invoiceId);
|
|
1206
|
+
const response = await fetch(pdf.download_url);
|
|
1207
|
+
if (!response.ok) throw new Error(`Failed to download PDF: ${response.status}`);
|
|
1208
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
1209
|
+
return { buffer: Buffer.from(arrayBuffer), fileName: pdf.file_name };
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
// src/webhooks/verifier.ts
|
|
1214
|
+
var import_crypto2 = require("crypto");
|
|
1215
|
+
var WebhookVerifier = class {
|
|
1216
|
+
/**
|
|
1217
|
+
* Creates a new WebhookVerifier
|
|
1218
|
+
*
|
|
1219
|
+
* @param secret - Your webhook secret from BeeL dashboard
|
|
1220
|
+
* @param toleranceSeconds - Maximum age of webhook events (default: 300 = 5 minutes)
|
|
1221
|
+
*/
|
|
1222
|
+
constructor(secret, toleranceSeconds = 300) {
|
|
1223
|
+
if (!secret || secret.trim().length === 0) {
|
|
1224
|
+
throw new Error("Webhook secret is required");
|
|
1225
|
+
}
|
|
1226
|
+
this.secret = secret;
|
|
1227
|
+
this.toleranceSeconds = toleranceSeconds;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Verify a webhook signature and return the parsed event
|
|
1231
|
+
*
|
|
1232
|
+
* @param rawBody - Raw request body (string or Buffer, before JSON parsing)
|
|
1233
|
+
* @param signatureHeader - Value of the `BeeL-Signature` header
|
|
1234
|
+
* @returns Parsed webhook event
|
|
1235
|
+
* @throws {WebhookVerificationError} If signature is invalid or event is too old
|
|
1236
|
+
*
|
|
1237
|
+
* @example Basic usage
|
|
1238
|
+
* ```typescript
|
|
1239
|
+
* const verifier = new WebhookVerifier('your_secret');
|
|
1240
|
+
* const event = verifier.verify(rawBody, signature);
|
|
1241
|
+
*
|
|
1242
|
+
* if (event.type === 'verifactu.status.updated') {
|
|
1243
|
+
* console.log('Invoice:', event.data.invoice_number);
|
|
1244
|
+
* console.log('Status:', event.data.new_status);
|
|
1245
|
+
* }
|
|
1246
|
+
* ```
|
|
1247
|
+
*/
|
|
1248
|
+
verify(rawBody, signatureHeader) {
|
|
1249
|
+
if (!signatureHeader) {
|
|
1250
|
+
throw new WebhookVerificationError("Missing BeeL-Signature header");
|
|
1251
|
+
}
|
|
1252
|
+
const { timestamp, signature } = this.parseSignatureHeader(signatureHeader);
|
|
1253
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1254
|
+
const age = Math.abs(now - timestamp);
|
|
1255
|
+
if (age > this.toleranceSeconds) {
|
|
1256
|
+
throw new WebhookVerificationError(
|
|
1257
|
+
`Webhook timestamp too old (${age}s ago, max ${this.toleranceSeconds}s allowed)`
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1260
|
+
const bodyString = Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : rawBody;
|
|
1261
|
+
const expectedSignature = this.computeSignature(timestamp, bodyString);
|
|
1262
|
+
if (!this.secureCompare(signature, expectedSignature)) {
|
|
1263
|
+
throw new WebhookVerificationError("Invalid webhook signature");
|
|
1264
|
+
}
|
|
1265
|
+
try {
|
|
1266
|
+
return JSON.parse(bodyString);
|
|
1267
|
+
} catch (error) {
|
|
1268
|
+
throw new WebhookVerificationError("Invalid JSON in webhook body");
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Parse the BeeL-Signature header
|
|
1273
|
+
*
|
|
1274
|
+
* Format: `t=1741362026,v1=3c4f7a2e...`
|
|
1275
|
+
*/
|
|
1276
|
+
parseSignatureHeader(header) {
|
|
1277
|
+
const parts = header.split(",");
|
|
1278
|
+
let timestamp;
|
|
1279
|
+
let signature;
|
|
1280
|
+
for (const part of parts) {
|
|
1281
|
+
const [key, value] = part.split("=", 2);
|
|
1282
|
+
if (key === "t") {
|
|
1283
|
+
timestamp = parseInt(value, 10);
|
|
1284
|
+
} else if (key === "v1") {
|
|
1285
|
+
signature = value;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
if (!timestamp || !signature) {
|
|
1289
|
+
throw new WebhookVerificationError(
|
|
1290
|
+
"Invalid signature header format (expected: t=timestamp,v1=signature)"
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
if (isNaN(timestamp)) {
|
|
1294
|
+
throw new WebhookVerificationError("Invalid timestamp in signature header");
|
|
1295
|
+
}
|
|
1296
|
+
return { timestamp, signature };
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Compute HMAC-SHA256 signature
|
|
1300
|
+
*
|
|
1301
|
+
* Algorithm:
|
|
1302
|
+
* 1. Build signed payload: `{timestamp}.{raw_body}`
|
|
1303
|
+
* 2. Compute: HMAC-SHA256(secret, signed_payload)
|
|
1304
|
+
* 3. Return hex digest
|
|
1305
|
+
*/
|
|
1306
|
+
computeSignature(timestamp, body) {
|
|
1307
|
+
const signedPayload = `${timestamp}.${body}`;
|
|
1308
|
+
return (0, import_crypto2.createHmac)("sha256", this.secret).update(signedPayload, "utf8").digest("hex");
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Constant-time string comparison to prevent timing attacks
|
|
1312
|
+
*/
|
|
1313
|
+
secureCompare(a, b) {
|
|
1314
|
+
if (a.length !== b.length) {
|
|
1315
|
+
return false;
|
|
1316
|
+
}
|
|
1317
|
+
const bufferA = Buffer.from(a, "utf8");
|
|
1318
|
+
const bufferB = Buffer.from(b, "utf8");
|
|
1319
|
+
return (0, import_crypto2.timingSafeEqual)(bufferA, bufferB);
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
var WebhookVerificationError = class extends Error {
|
|
1323
|
+
constructor(message) {
|
|
1324
|
+
super(message);
|
|
1325
|
+
this.name = "WebhookVerificationError";
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
// src/generated-webhooks/models/AccountClaimedEvent.ts
|
|
1330
|
+
var AccountClaimedEvent;
|
|
1331
|
+
((AccountClaimedEvent2) => {
|
|
1332
|
+
let type;
|
|
1333
|
+
((type2) => {
|
|
1334
|
+
type2["ACCOUNT_CLAIMED"] = "account.claimed";
|
|
1335
|
+
})(type = AccountClaimedEvent2.type || (AccountClaimedEvent2.type = {}));
|
|
1336
|
+
})(AccountClaimedEvent || (AccountClaimedEvent = {}));
|
|
1337
|
+
|
|
1338
|
+
// src/generated-webhooks/models/CompanyCreatedEvent.ts
|
|
1339
|
+
var CompanyCreatedEvent;
|
|
1340
|
+
((CompanyCreatedEvent2) => {
|
|
1341
|
+
let type;
|
|
1342
|
+
((type2) => {
|
|
1343
|
+
type2["COMPANY_CREATED"] = "company.created";
|
|
1344
|
+
})(type = CompanyCreatedEvent2.type || (CompanyCreatedEvent2.type = {}));
|
|
1345
|
+
})(CompanyCreatedEvent || (CompanyCreatedEvent = {}));
|
|
1346
|
+
|
|
1347
|
+
// src/generated-webhooks/models/InvoiceEmailSentEvent.ts
|
|
1348
|
+
var InvoiceEmailSentEvent;
|
|
1349
|
+
((InvoiceEmailSentEvent2) => {
|
|
1350
|
+
let type;
|
|
1351
|
+
((type2) => {
|
|
1352
|
+
type2["INVOICE_EMAIL_SENT"] = "invoice.email.sent";
|
|
1353
|
+
})(type = InvoiceEmailSentEvent2.type || (InvoiceEmailSentEvent2.type = {}));
|
|
1354
|
+
})(InvoiceEmailSentEvent || (InvoiceEmailSentEvent = {}));
|
|
1355
|
+
|
|
1356
|
+
// src/generated-webhooks/models/InvoiceIssuedEvent.ts
|
|
1357
|
+
var InvoiceIssuedEvent;
|
|
1358
|
+
((InvoiceIssuedEvent2) => {
|
|
1359
|
+
let type;
|
|
1360
|
+
((type2) => {
|
|
1361
|
+
type2["INVOICE_ISSUED"] = "invoice.issued";
|
|
1362
|
+
})(type = InvoiceIssuedEvent2.type || (InvoiceIssuedEvent2.type = {}));
|
|
1363
|
+
})(InvoiceIssuedEvent || (InvoiceIssuedEvent = {}));
|
|
1364
|
+
|
|
1365
|
+
// src/generated-webhooks/models/InvoiceVoidedEvent.ts
|
|
1366
|
+
var InvoiceVoidedEvent;
|
|
1367
|
+
((InvoiceVoidedEvent2) => {
|
|
1368
|
+
let type;
|
|
1369
|
+
((type2) => {
|
|
1370
|
+
type2["INVOICE_VOIDED"] = "invoice.voided";
|
|
1371
|
+
})(type = InvoiceVoidedEvent2.type || (InvoiceVoidedEvent2.type = {}));
|
|
1372
|
+
})(InvoiceVoidedEvent || (InvoiceVoidedEvent = {}));
|
|
1373
|
+
|
|
1374
|
+
// src/generated-webhooks/models/RecurringInvoicePausedEvent.ts
|
|
1375
|
+
var RecurringInvoicePausedEvent;
|
|
1376
|
+
((RecurringInvoicePausedEvent2) => {
|
|
1377
|
+
let type;
|
|
1378
|
+
((type2) => {
|
|
1379
|
+
type2["RECURRING_INVOICE_PAUSED"] = "recurring_invoice.paused";
|
|
1380
|
+
})(type = RecurringInvoicePausedEvent2.type || (RecurringInvoicePausedEvent2.type = {}));
|
|
1381
|
+
})(RecurringInvoicePausedEvent || (RecurringInvoicePausedEvent = {}));
|
|
1382
|
+
|
|
1383
|
+
// src/generated-webhooks/models/RepresentationSignedEvent.ts
|
|
1384
|
+
var RepresentationSignedEvent;
|
|
1385
|
+
((RepresentationSignedEvent2) => {
|
|
1386
|
+
let type;
|
|
1387
|
+
((type2) => {
|
|
1388
|
+
type2["REPRESENTATION_SIGNED"] = "representation.signed";
|
|
1389
|
+
})(type = RepresentationSignedEvent2.type || (RepresentationSignedEvent2.type = {}));
|
|
1390
|
+
})(RepresentationSignedEvent || (RepresentationSignedEvent = {}));
|
|
1391
|
+
|
|
1392
|
+
// src/generated-webhooks/models/VeriFactuStatusUpdatedEvent.ts
|
|
1393
|
+
var VeriFactuStatusUpdatedEvent;
|
|
1394
|
+
((VeriFactuStatusUpdatedEvent2) => {
|
|
1395
|
+
let type;
|
|
1396
|
+
((type2) => {
|
|
1397
|
+
type2["VERIFACTU_STATUS_UPDATED"] = "verifactu.status.updated";
|
|
1398
|
+
})(type = VeriFactuStatusUpdatedEvent2.type || (VeriFactuStatusUpdatedEvent2.type = {}));
|
|
1399
|
+
})(VeriFactuStatusUpdatedEvent || (VeriFactuStatusUpdatedEvent = {}));
|
|
1400
|
+
|
|
1401
|
+
// src/generated-webhooks/models/VeriFactuSubmissionStatus.ts
|
|
1402
|
+
var VeriFactuSubmissionStatus = /* @__PURE__ */ ((VeriFactuSubmissionStatus2) => {
|
|
1403
|
+
VeriFactuSubmissionStatus2["PENDING"] = "PENDING";
|
|
1404
|
+
VeriFactuSubmissionStatus2["ACCEPTED"] = "ACCEPTED";
|
|
1405
|
+
VeriFactuSubmissionStatus2["VOIDED"] = "VOIDED";
|
|
1406
|
+
VeriFactuSubmissionStatus2["REJECTED"] = "REJECTED";
|
|
1407
|
+
return VeriFactuSubmissionStatus2;
|
|
1408
|
+
})(VeriFactuSubmissionStatus || {});
|
|
1409
|
+
|
|
1410
|
+
// src/generated-webhooks/models/WebhookEventType.ts
|
|
1411
|
+
var WebhookEventType = /* @__PURE__ */ ((WebhookEventType2) => {
|
|
1412
|
+
WebhookEventType2["VERIFACTU_STATUS_UPDATED"] = "verifactu.status.updated";
|
|
1413
|
+
WebhookEventType2["INVOICE_ISSUED"] = "invoice.issued";
|
|
1414
|
+
WebhookEventType2["INVOICE_EMAIL_SENT"] = "invoice.email.sent";
|
|
1415
|
+
WebhookEventType2["INVOICE_VOIDED"] = "invoice.voided";
|
|
1416
|
+
WebhookEventType2["RECURRING_INVOICE_PAUSED"] = "recurring_invoice.paused";
|
|
1417
|
+
WebhookEventType2["ACCOUNT_CLAIMED"] = "account.claimed";
|
|
1418
|
+
WebhookEventType2["COMPANY_CREATED"] = "company.created";
|
|
1419
|
+
WebhookEventType2["REPRESENTATION_SIGNED"] = "representation.signed";
|
|
1420
|
+
return WebhookEventType2;
|
|
1421
|
+
})(WebhookEventType || {});
|
|
1422
|
+
|
|
1423
|
+
// src/builders/customer-builder.ts
|
|
1424
|
+
var CustomerBuilder = class _CustomerBuilder {
|
|
1425
|
+
constructor() {
|
|
1426
|
+
}
|
|
1427
|
+
static create() {
|
|
1428
|
+
return new _CustomerBuilder();
|
|
1429
|
+
}
|
|
1430
|
+
name(name) {
|
|
1431
|
+
this._name = name;
|
|
1432
|
+
return this;
|
|
1433
|
+
}
|
|
1434
|
+
nif(nif) {
|
|
1435
|
+
this._nif = nif;
|
|
1436
|
+
return this;
|
|
1437
|
+
}
|
|
1438
|
+
email(email) {
|
|
1439
|
+
this._email = email;
|
|
1440
|
+
return this;
|
|
1441
|
+
}
|
|
1442
|
+
phone(phone) {
|
|
1443
|
+
this._phone = phone;
|
|
1444
|
+
return this;
|
|
1445
|
+
}
|
|
1446
|
+
address(street, number, postalCode, city, province, country, countryCode = "ES") {
|
|
1447
|
+
this._address = { street, number, postal_code: postalCode, city, province, country, country_code: countryCode };
|
|
1448
|
+
return this;
|
|
1449
|
+
}
|
|
1450
|
+
notes(notes) {
|
|
1451
|
+
this._notes = notes;
|
|
1452
|
+
return this;
|
|
1453
|
+
}
|
|
1454
|
+
build() {
|
|
1455
|
+
if (!this._name || this._name.trim().length === 0) throw new Error("Legal name is required");
|
|
1456
|
+
if (!this._nif || this._nif.trim().length === 0) throw new Error("NIF/CIF is required");
|
|
1457
|
+
if (!this._address) throw new Error("Address is required");
|
|
1458
|
+
return {
|
|
1459
|
+
legal_name: this._name,
|
|
1460
|
+
nif: this._nif,
|
|
1461
|
+
email: this._email,
|
|
1462
|
+
phone: this._phone,
|
|
1463
|
+
address: this._address,
|
|
1464
|
+
notes: this._notes
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
|
|
1469
|
+
// src/builders/invoice-builder.ts
|
|
1470
|
+
var InvoiceBuilder = class _InvoiceBuilder {
|
|
1471
|
+
constructor() {
|
|
1472
|
+
this._type = "STANDARD";
|
|
1473
|
+
this._lines = [];
|
|
1474
|
+
}
|
|
1475
|
+
static create() {
|
|
1476
|
+
return new _InvoiceBuilder();
|
|
1477
|
+
}
|
|
1478
|
+
type(type) {
|
|
1479
|
+
this._type = type;
|
|
1480
|
+
return this;
|
|
1481
|
+
}
|
|
1482
|
+
forCustomer(customerId) {
|
|
1483
|
+
this._customerId = customerId;
|
|
1484
|
+
return this;
|
|
1485
|
+
}
|
|
1486
|
+
operationDate(date) {
|
|
1487
|
+
this._operationDate = date instanceof Date ? date.toISOString().split("T")[0] : date;
|
|
1488
|
+
return this;
|
|
1489
|
+
}
|
|
1490
|
+
dueDate(date) {
|
|
1491
|
+
this._dueDate = date instanceof Date ? date.toISOString().split("T")[0] : date;
|
|
1492
|
+
return this;
|
|
1493
|
+
}
|
|
1494
|
+
addLine(description, quantity, unitPrice, discountPercentage = 0) {
|
|
1495
|
+
this._lines.push({ line_type: "NORMAL", description, quantity, unit_price: unitPrice, discount_percentage: discountPercentage });
|
|
1496
|
+
return this;
|
|
1497
|
+
}
|
|
1498
|
+
addLineObject(line) {
|
|
1499
|
+
this._lines.push(line);
|
|
1500
|
+
return this;
|
|
1501
|
+
}
|
|
1502
|
+
notes(notes) {
|
|
1503
|
+
this._notes = notes;
|
|
1504
|
+
return this;
|
|
1505
|
+
}
|
|
1506
|
+
series(id) {
|
|
1507
|
+
this._seriesId = id;
|
|
1508
|
+
return this;
|
|
1509
|
+
}
|
|
1510
|
+
metadata(data) {
|
|
1511
|
+
this._metadata = data;
|
|
1512
|
+
return this;
|
|
1513
|
+
}
|
|
1514
|
+
build() {
|
|
1515
|
+
if (!this._customerId) throw new Error("Customer ID is required");
|
|
1516
|
+
if (this._lines.length === 0) throw new Error("At least one invoice line is required");
|
|
1517
|
+
const recipient = { customer_id: this._customerId };
|
|
1518
|
+
return {
|
|
1519
|
+
type: this._type,
|
|
1520
|
+
operation_date: this._operationDate,
|
|
1521
|
+
due_date: this._dueDate,
|
|
1522
|
+
recipient,
|
|
1523
|
+
lines: this._lines,
|
|
1524
|
+
notes: this._notes,
|
|
1525
|
+
series_id: this._seriesId,
|
|
1526
|
+
metadata: this._metadata
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1531
|
+
0 && (module.exports = {
|
|
1532
|
+
AccountCompaniesResource,
|
|
1533
|
+
AccountInvitationsResource,
|
|
1534
|
+
AccountMembersResource,
|
|
1535
|
+
AccountScope,
|
|
1536
|
+
AccountWebhooksResource,
|
|
1537
|
+
AccountsResource,
|
|
1538
|
+
BeeL,
|
|
1539
|
+
BeeLApiError,
|
|
1540
|
+
BeeLAuthError,
|
|
1541
|
+
BeeLConflictError,
|
|
1542
|
+
BeeLNotFoundError,
|
|
1543
|
+
BeeLRateLimitError,
|
|
1544
|
+
BeeLValidationError,
|
|
1545
|
+
CompanyCustomersResource,
|
|
1546
|
+
CompanyInvoicesResource,
|
|
1547
|
+
CompanyProductsResource,
|
|
1548
|
+
CompanyRecurringInvoicesResource,
|
|
1549
|
+
CompanyScope,
|
|
1550
|
+
CompanySeriesResource,
|
|
1551
|
+
CustomerBuilder,
|
|
1552
|
+
InvoiceBuilder,
|
|
1553
|
+
VeriFactuSubmissionStatus,
|
|
1554
|
+
WebhookEventType,
|
|
1555
|
+
WebhookVerificationError,
|
|
1556
|
+
WebhookVerifier
|
|
1557
|
+
});
|
|
52
1558
|
//# sourceMappingURL=index.js.map
|