@frihet/mcp-server 1.15.2 → 1.15.3

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
@@ -39,7 +39,7 @@
39
39
  | **ChatGPT Apps** | Coming soon | [chatgpt.com](https://chatgpt.com) |
40
40
  | **Anthropic Claude Directory** | Coming soon | [claude.ai/settings/connectors](https://claude.ai/settings/connectors) |
41
41
 
42
- > **Tool count:** npm `latest` (1.15.2) ships all 157 tools, same as the remote endpoint (`mcp.frihet.io`).
42
+ > **Tool count:** npm `latest` (1.15.3) ships all 157 tools, same as the remote endpoint (`mcp.frihet.io`).
43
43
 
44
44
  ---
45
45
 
@@ -58,6 +58,20 @@ Claude: Done. Invoice INV-2026-089 created. Total: 3,000.00 EUR + 21% IVA = 3,6
58
58
 
59
59
  ---
60
60
 
61
+ ## Try it instantly (no signup)
62
+
63
+ Kick the tires with zero setup — no account, no API key:
64
+
65
+ ```bash
66
+ FRIHET_DEMO=1 npx -y @frihet/mcp-server
67
+ ```
68
+
69
+ In demo mode the server answers from realistic **example fixtures** (Spanish invoices with IVA/IGIC, expenses, clients, products, a bank account, and more) — every record uses `demo_`-prefixed IDs and the server prints a `DEMO MODE` banner on startup. **Nothing is persisted** and no network call is ever made. Writes are simulated and fiscal actions (e-invoice, VeriFactu, TicketBAI, FACe, payroll) return a clearly-labeled simulation — never a real submission to any tax authority.
70
+
71
+ When you're ready for your real data, drop the flag and add your key ([app.frihet.io](https://app.frihet.io) → Settings → API keys). See [Install](#install) below.
72
+
73
+ ---
74
+
61
75
  ## Install
62
76
 
63
77
  ### One-line (Claude Code, Cursor, Copilot, Codex, Windsurf, Gemini CLI, and more)
@@ -66,6 +80,24 @@ Claude: Done. Invoice INV-2026-089 created. Total: 3,000.00 EUR + 21% IVA = 3,6
66
80
  npx skills add Frihet-io/frihet-mcp
67
81
  ```
68
82
 
83
+ ### Claude Code plugin (skill + MCP server in one install)
84
+
85
+ This repository is also a Claude Code plugin (`frihet-erp`): installing it wires up both the business-management skill and the MCP server.
86
+
87
+ ```bash
88
+ # Try it locally
89
+ claude --plugin-dir /path/to/frihet-mcp
90
+ ```
91
+
92
+ Once available in the community marketplace:
93
+
94
+ ```text
95
+ /plugin marketplace add anthropics/claude-plugins-community
96
+ /plugin install frihet-erp@claude-community
97
+ ```
98
+
99
+ Skill invocation: `/frihet-erp:frihet-mcp`. The bundled `.mcp.json` launches `@frihet/mcp-server` via `npx` — set `FRIHET_API_KEY` in your environment (get one at [app.frihet.io](https://app.frihet.io) → Settings → API keys).
100
+
69
101
  ### Claude Code / Claude Desktop
70
102
 
71
103
  ```json
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Demo mode (`FRIHET_DEMO=1`) — DemoFrihetClient contract + fixture PII safety.
3
+ *
4
+ * Verifies the fixture-backed client serves stamped example data with ZERO
5
+ * network calls, simulates writes with a demo id, labels fiscal actions as
6
+ * simulated, and that no fixture email leaks a non-@example.com domain.
7
+ *
8
+ * Run: npm test (after build)
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=demo-mode.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo-mode.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/demo-mode.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Demo mode (`FRIHET_DEMO=1`) — DemoFrihetClient contract + fixture PII safety.
3
+ *
4
+ * Verifies the fixture-backed client serves stamped example data with ZERO
5
+ * network calls, simulates writes with a demo id, labels fiscal actions as
6
+ * simulated, and that no fixture email leaks a non-@example.com domain.
7
+ *
8
+ * Run: npm test (after build)
9
+ */
10
+ import { test, describe } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { DemoFrihetClient } from "../demo-client.js";
13
+ import * as fixtures from "../demo-fixtures.js";
14
+ describe("DemoFrihetClient — reads", () => {
15
+ test("listInvoices returns a non-empty stamped PaginatedResponse", async () => {
16
+ const client = new DemoFrihetClient();
17
+ const res = await client.listInvoices();
18
+ assert.ok(Array.isArray(res.data), "data is an array");
19
+ assert.ok(res.data.length > 0, "data is non-empty");
20
+ assert.equal(res.total, res.data.length);
21
+ assert.equal(res._demo, true);
22
+ assert.ok(res._demoNotice, "_demoNotice present");
23
+ });
24
+ test("getInvoice(<fixture id>) returns the fixture stamped _demo:true", async () => {
25
+ const client = new DemoFrihetClient();
26
+ const firstId = fixtures.demoInvoices[0].id;
27
+ const res = await client.getInvoice(firstId);
28
+ assert.equal(res.id, firstId);
29
+ assert.equal(res._demo, true);
30
+ assert.ok(res._demoNotice, "_demoNotice present");
31
+ });
32
+ });
33
+ describe("DemoFrihetClient — writes are simulated", () => {
34
+ test("createInvoice returns _demo:true with a demo_-prefixed id, purely", async () => {
35
+ const client = new DemoFrihetClient();
36
+ const res = await client.createInvoice({
37
+ clientName: "Test Client",
38
+ items: [{ description: "Work", quantity: 2, unitPrice: 100 }],
39
+ taxRate: 21,
40
+ });
41
+ assert.equal(res._demo, true);
42
+ assert.equal(typeof res.id, "string");
43
+ assert.ok(res.id.startsWith("demo_"), `id "${res.id}" starts with demo_`);
44
+ // Echoes input + computes totals.
45
+ assert.equal(res.clientName, "Test Client");
46
+ assert.equal(res.subtotal, 200);
47
+ assert.equal(res.taxAmount, 42);
48
+ assert.equal(res.total, 242);
49
+ // WRITE notice communicates non-persistence.
50
+ assert.match(res._demoNotice, /Simulated — not persisted/);
51
+ });
52
+ test("createInvoice is a pure function — no throw, no network, repeatable", async () => {
53
+ const client = new DemoFrihetClient();
54
+ // Called twice back-to-back; neither throws nor hangs on a socket.
55
+ const a = await client.createInvoice({ clientName: "A", items: [] });
56
+ const b = await client.createInvoice({ clientName: "B", items: [] });
57
+ assert.equal(a._demo, true);
58
+ assert.equal(b._demo, true);
59
+ assert.notEqual(a.id, b.id, "ids are distinct across calls");
60
+ });
61
+ });
62
+ describe("DemoFrihetClient — fiscal actions are simulated only", () => {
63
+ test("sendEInvoice returns _demo:true + a simulated queued status, never throws", async () => {
64
+ const client = new DemoFrihetClient();
65
+ const res = await client.sendEInvoice({ invoiceId: "demo_inv_001", format: "facturae", dispatchMode: "peppol" });
66
+ assert.equal(res.status, "queued");
67
+ assert.equal(typeof res.workflowRunId, "string");
68
+ assert.equal(res._demo, true);
69
+ const notice = res._demoNotice;
70
+ assert.ok(notice, "_demoNotice present");
71
+ assert.match(notice, /no submission was made to any tax authority/);
72
+ });
73
+ test("faceSubmit + ticketbaiSubmit are labeled simulated, never real submissions", async () => {
74
+ const client = new DemoFrihetClient();
75
+ const face = await client.faceSubmit({ invoiceId: "demo_inv_001", mode: "sandbox" });
76
+ assert.equal(face.status, "submitted");
77
+ assert.equal(face._demo, true);
78
+ const tbai = await client.ticketbaiSubmit({ invoiceId: "demo_inv_001", sandbox: true });
79
+ assert.equal(tbai._demo, true);
80
+ assert.match(tbai._demoNotice, /no submission was made to any tax authority/);
81
+ });
82
+ });
83
+ describe("demo fixtures — PII safety", () => {
84
+ test("every email string in the fixtures ends with @example.com", () => {
85
+ // Collect every string value that looks like an email across all fixture
86
+ // exports; assert none uses a domain other than example.com.
87
+ const emailRe = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
88
+ const emails = [];
89
+ const seen = new Set();
90
+ const walk = (val) => {
91
+ if (val == null)
92
+ return;
93
+ if (typeof val === "string") {
94
+ const matches = val.match(emailRe);
95
+ if (matches)
96
+ emails.push(...matches);
97
+ return;
98
+ }
99
+ if (typeof val !== "object")
100
+ return;
101
+ if (seen.has(val))
102
+ return;
103
+ seen.add(val);
104
+ for (const v of Object.values(val))
105
+ walk(v);
106
+ };
107
+ walk(fixtures);
108
+ assert.ok(emails.length > 0, "fixtures contain at least one email (sanity)");
109
+ for (const email of emails) {
110
+ assert.ok(email.endsWith("@example.com"), `email "${email}" must be under @example.com`);
111
+ }
112
+ });
113
+ test("fixtures use the ECBS/AEAT test IBAN, not a real one", () => {
114
+ assert.equal(fixtures.DEMO_TEST_IBAN, "ES9121000418450200051332");
115
+ const account = fixtures.demoBankAccounts[0];
116
+ assert.equal(account.iban, fixtures.DEMO_TEST_IBAN);
117
+ });
118
+ });
119
+ //# sourceMappingURL=demo-mode.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo-mode.test.js","sourceRoot":"","sources":["../../src/__tests__/demo-mode.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,468 @@
1
+ /**
2
+ * DemoFrihetClient — the `FRIHET_DEMO=1` seam.
3
+ *
4
+ * A drop-in IFrihetClient that makes ZERO network calls: it serves the canned
5
+ * PII-safe fixtures in demo-fixtures.ts. index.ts swaps this in for FrihetClient
6
+ * when demo mode is on, so tools (which stringify the client's return value)
7
+ * automatically propagate the `_demo`/`_demoNotice` banner without any change
8
+ * under src/tools/.
9
+ *
10
+ * Response contract (see SPEC-mcp-demo-mode.md option B/C):
11
+ * - reads/lists → fixture data stamped `_demo:true` (READ notice).
12
+ * - lists without fixtures → EMPTY PaginatedResponse, still stamped.
13
+ * - writes → plausible fixture-shaped object with a `demo_`-prefixed id
14
+ * (WRITE notice "…Simulated — not persisted.").
15
+ * - fiscal / e-invoice / email / payroll → SIMULATED labeled response, NEVER
16
+ * a real submission (FISCAL notice).
17
+ * - delete / remove methods → resolve void (interface return type forbids a
18
+ * stamp; this is the one accepted, documented gap).
19
+ */
20
+ import type { IFrihetClient } from "./client-interface.js";
21
+ import type { PaginatedResponse } from "./types.js";
22
+ type Rec = Record<string, unknown>;
23
+ export declare class DemoFrihetClient implements IFrihetClient {
24
+ listInvoices(params?: {
25
+ limit?: number;
26
+ offset?: number;
27
+ }): Promise<PaginatedResponse<Rec>>;
28
+ getInvoice(id: string): Promise<Rec>;
29
+ createInvoice(data: Rec): Promise<Rec>;
30
+ updateInvoice(id: string, data: Rec): Promise<Rec>;
31
+ deleteInvoice(_id: string): Promise<void>;
32
+ searchInvoices(query: string, params?: {
33
+ limit?: number;
34
+ offset?: number;
35
+ }): Promise<PaginatedResponse<Rec>>;
36
+ listExpenses(params?: {
37
+ limit?: number;
38
+ offset?: number;
39
+ }): Promise<PaginatedResponse<Rec>>;
40
+ getExpense(id: string): Promise<Rec>;
41
+ createExpense(data: Rec): Promise<Rec>;
42
+ updateExpense(id: string, data: Rec): Promise<Rec>;
43
+ deleteExpense(_id: string): Promise<void>;
44
+ listClients(params?: {
45
+ limit?: number;
46
+ offset?: number;
47
+ }): Promise<PaginatedResponse<Rec>>;
48
+ getClient(id: string): Promise<Rec>;
49
+ createClient(data: Rec): Promise<Rec>;
50
+ updateClient(id: string, data: Rec): Promise<Rec>;
51
+ deleteClient(_id: string): Promise<void>;
52
+ listProducts(params?: {
53
+ limit?: number;
54
+ offset?: number;
55
+ }): Promise<PaginatedResponse<Rec>>;
56
+ getProduct(id: string): Promise<Rec>;
57
+ createProduct(data: Rec): Promise<Rec>;
58
+ updateProduct(id: string, data: Rec): Promise<Rec>;
59
+ deleteProduct(_id: string): Promise<void>;
60
+ listQuotes(params?: {
61
+ limit?: number;
62
+ offset?: number;
63
+ }): Promise<PaginatedResponse<Rec>>;
64
+ getQuote(id: string): Promise<Rec>;
65
+ createQuote(data: Rec): Promise<Rec>;
66
+ updateQuote(id: string, data: Rec): Promise<Rec>;
67
+ deleteQuote(_id: string): Promise<void>;
68
+ listVendors(params?: {
69
+ limit?: number;
70
+ offset?: number;
71
+ }): Promise<PaginatedResponse<Rec>>;
72
+ getVendor(id: string): Promise<Rec>;
73
+ createVendor(data: Rec): Promise<Rec>;
74
+ updateVendor(id: string, data: Rec): Promise<Rec>;
75
+ deleteVendor(_id: string): Promise<void>;
76
+ sendInvoice(id: string, to?: string): Promise<Rec>;
77
+ markInvoicePaid(id: string, paidDate?: string): Promise<Rec>;
78
+ getInvoicePdf(id: string): Promise<Rec>;
79
+ getInvoiceEInvoice(invoiceId: string): Promise<Rec>;
80
+ createCreditNote(invoiceId: string, data: {
81
+ reason: string;
82
+ reasonDescription?: string;
83
+ fullCredit?: boolean;
84
+ issueDate?: string;
85
+ }): Promise<Rec>;
86
+ applyLateFee(invoiceId: string, data?: {
87
+ amount?: number;
88
+ daysOverdue?: number;
89
+ }): Promise<Rec>;
90
+ sendQuote(id: string, to?: string): Promise<Rec>;
91
+ listWebhooks(params?: {
92
+ limit?: number;
93
+ offset?: number;
94
+ }): Promise<PaginatedResponse<Rec>>;
95
+ getWebhook(id: string): Promise<Rec>;
96
+ createWebhook(data: Rec): Promise<Rec>;
97
+ updateWebhook(id: string, data: Rec): Promise<Rec>;
98
+ deleteWebhook(_id: string): Promise<void>;
99
+ listClientContacts(_clientId: string, params?: {
100
+ limit?: number;
101
+ offset?: number;
102
+ }): Promise<PaginatedResponse<Rec>>;
103
+ createClientContact(clientId: string, data: Rec): Promise<Rec>;
104
+ deleteClientContact(_clientId: string, _contactId: string): Promise<void>;
105
+ listClientActivities(_clientId: string, params?: {
106
+ limit?: number;
107
+ offset?: number;
108
+ }): Promise<PaginatedResponse<Rec>>;
109
+ logClientActivity(clientId: string, data: Rec): Promise<Rec>;
110
+ listClientNotes(_clientId: string, params?: {
111
+ limit?: number;
112
+ offset?: number;
113
+ }): Promise<PaginatedResponse<Rec>>;
114
+ createClientNote(clientId: string, data: Rec): Promise<Rec>;
115
+ deleteClientNote(_clientId: string, _noteId: string): Promise<void>;
116
+ listDeposits(params?: {
117
+ limit?: number;
118
+ offset?: number;
119
+ }): Promise<PaginatedResponse<Rec>>;
120
+ getDeposit(id: string): Promise<Rec>;
121
+ createDeposit(data: Rec): Promise<Rec>;
122
+ updateDeposit(id: string, data: Rec): Promise<Rec>;
123
+ deleteDeposit(_id: string): Promise<void>;
124
+ applyDeposit(id: string, data?: Rec): Promise<Rec>;
125
+ refundDeposit(id: string, data?: Rec): Promise<Rec>;
126
+ getBusinessContext(): Promise<Rec>;
127
+ getMonthlySummary(month?: string): Promise<Rec>;
128
+ getQuarterlyTaxes(quarter?: string): Promise<Rec>;
129
+ sendEInvoice(_params: {
130
+ invoiceId: string;
131
+ format: string;
132
+ dispatchMode: string;
133
+ }): Promise<{
134
+ workflowRunId: string;
135
+ status: "queued";
136
+ estimatedCompletionSec: number;
137
+ }>;
138
+ getEInvoiceStatus(_workflowRunId: string): Promise<{
139
+ status: "queued" | "running" | "succeeded" | "failed" | "cancelled";
140
+ step: string;
141
+ error?: string;
142
+ ackId?: string;
143
+ pdfA3Url?: string;
144
+ xmlUrl?: string;
145
+ }>;
146
+ validateEInvoiceXml(_params: {
147
+ xml: string;
148
+ format: string;
149
+ }): Promise<{
150
+ valid: boolean;
151
+ errors: Array<{
152
+ severity: string;
153
+ location: string;
154
+ message: string;
155
+ rule: string;
156
+ }>;
157
+ validator: "kosit" | "mustang" | "xsd" | "schematron";
158
+ durationMs: number;
159
+ }>;
160
+ exportDatev(params: {
161
+ periodStart: string;
162
+ periodEnd: string;
163
+ format: string;
164
+ }): Promise<{
165
+ fileUrl: string;
166
+ filename: string;
167
+ rowCount: number;
168
+ fiscalPeriod: string;
169
+ encoding: "cp1252";
170
+ }>;
171
+ exportEInvoice(params: {
172
+ invoiceId: string;
173
+ format: string;
174
+ signed?: boolean;
175
+ }): Promise<{
176
+ xmlUrl: string;
177
+ filename: string;
178
+ format: string;
179
+ signed: boolean;
180
+ }>;
181
+ faceSubmit(params: {
182
+ invoiceId: string;
183
+ mode: "mock" | "sandbox" | "production";
184
+ }): Promise<{
185
+ registroFACe: string;
186
+ status: "submitted" | "error";
187
+ submittedAt: string;
188
+ mode: string;
189
+ }>;
190
+ faceStatus(_params: {
191
+ invoiceId: string;
192
+ }): Promise<{
193
+ registroFACe: string;
194
+ statusCode: string;
195
+ statusDescription: string;
196
+ rejectionReason?: string;
197
+ }>;
198
+ ticketbaiSubmit(params: {
199
+ invoiceId: string;
200
+ sandbox: boolean;
201
+ }): Promise<{
202
+ tbaiId: string;
203
+ territory: "bizkaia" | "gipuzkoa" | "araba";
204
+ status: "submitted" | "accepted" | "rejected" | "error";
205
+ sandbox: boolean;
206
+ qrUrl?: string;
207
+ }>;
208
+ ticketbaiStatus(_params: {
209
+ invoiceId: string;
210
+ }): Promise<{
211
+ tbaiId: string;
212
+ territory: "bizkaia" | "gipuzkoa" | "araba";
213
+ status: "submitted" | "accepted" | "rejected" | "error";
214
+ rejectionReason?: string;
215
+ error?: string;
216
+ }>;
217
+ listReservations(params?: {
218
+ limit?: number;
219
+ offset?: number;
220
+ }): Promise<PaginatedResponse<Rec>>;
221
+ getReservation(id: string): Promise<Rec>;
222
+ createReservation(data: Rec): Promise<Rec>;
223
+ listProperties(params?: {
224
+ limit?: number;
225
+ offset?: number;
226
+ }): Promise<PaginatedResponse<Rec>>;
227
+ syncChannel(channelId: string, direction: "pull" | "push" | "both"): Promise<Rec>;
228
+ listTerminals(params?: {
229
+ limit?: number;
230
+ offset?: number;
231
+ }): Promise<PaginatedResponse<Rec>>;
232
+ getSale(id: string): Promise<Rec>;
233
+ listSales(params?: {
234
+ limit?: number;
235
+ offset?: number;
236
+ }): Promise<PaginatedResponse<Rec>>;
237
+ refundSale(id: string, data?: {
238
+ amountCents?: number;
239
+ reason?: string;
240
+ }): Promise<Rec>;
241
+ listKitchenTickets(params?: {
242
+ limit?: number;
243
+ offset?: number;
244
+ }): Promise<PaginatedResponse<Rec>>;
245
+ getKitchenTicket(id: string): Promise<Rec>;
246
+ updateKitchenTicket(id: string, data: Rec): Promise<Rec>;
247
+ listKitchenStations(params?: {
248
+ limit?: number;
249
+ offset?: number;
250
+ }): Promise<PaginatedResponse<Rec>>;
251
+ listMenuItems(params?: {
252
+ limit?: number;
253
+ offset?: number;
254
+ }): Promise<PaginatedResponse<Rec>>;
255
+ listBankAccounts(params?: {
256
+ limit?: number;
257
+ offset?: number;
258
+ }): Promise<PaginatedResponse<Rec>>;
259
+ getBankAccount(id: string): Promise<Rec>;
260
+ listTransactions(params?: {
261
+ limit?: number;
262
+ offset?: number;
263
+ }): Promise<PaginatedResponse<Rec>>;
264
+ categorizeTransaction(id: string, data: {
265
+ category: string;
266
+ notes?: string;
267
+ }): Promise<Rec>;
268
+ matchTransactionToDocument(transactionId: string, data: {
269
+ documentId: string;
270
+ documentType: "invoice" | "expense";
271
+ notes?: string;
272
+ }): Promise<Rec>;
273
+ getFiscalModeloSummary(modeloCode: string, period?: string): Promise<Rec>;
274
+ getVerifactuStatus(invoiceId: string): Promise<Rec>;
275
+ resubmitVerifactu(invoiceId: string): Promise<Rec>;
276
+ getTicketbaiStatus(invoiceId: string): Promise<Rec>;
277
+ listTimeEntries(params?: {
278
+ limit?: number;
279
+ offset?: number;
280
+ }): Promise<PaginatedResponse<Rec>>;
281
+ getTimeEntry(id: string): Promise<Rec>;
282
+ createTimeEntry(data: Rec): Promise<Rec>;
283
+ updateTimeEntry(id: string, data: Rec): Promise<Rec>;
284
+ deleteTimeEntry(_id: string): Promise<void>;
285
+ getTimeSummary(params: {
286
+ from: string;
287
+ to: string;
288
+ }): Promise<Rec>;
289
+ listRecurringInvoices(params?: {
290
+ limit?: number;
291
+ offset?: number;
292
+ }): Promise<PaginatedResponse<Rec>>;
293
+ getRecurringInvoice(id: string): Promise<Rec>;
294
+ createRecurringInvoice(data: Rec): Promise<Rec>;
295
+ updateRecurringInvoice(id: string, data: Rec): Promise<Rec>;
296
+ pauseRecurringInvoice(id: string): Promise<Rec>;
297
+ resumeRecurringInvoice(id: string): Promise<Rec>;
298
+ deleteRecurringInvoice(_id: string): Promise<void>;
299
+ runRecurringNow(templateId: string, options?: {
300
+ draftOnly?: boolean;
301
+ }): Promise<Rec>;
302
+ listTeamMembers(params?: {
303
+ limit?: number;
304
+ offset?: number;
305
+ }): Promise<PaginatedResponse<Rec>>;
306
+ inviteTeamMember(data: {
307
+ email: string;
308
+ role: string;
309
+ name?: string;
310
+ }): Promise<Rec>;
311
+ updateTeamMemberRole(memberId: string, role: string): Promise<Rec>;
312
+ removeTeamMember(_memberId: string): Promise<void>;
313
+ approveGLEntry(entryId: string, notes?: string): Promise<Rec>;
314
+ rejectGLEntry(entryId: string, reason: string): Promise<Rec>;
315
+ getGLEntryAuditLog(entryId: string): Promise<Rec>;
316
+ addCustomPortalDomain(data: {
317
+ domain: string;
318
+ workspaceId?: string;
319
+ }): Promise<Rec>;
320
+ verifyCustomPortalDomain(data: {
321
+ domain: string;
322
+ }): Promise<Rec>;
323
+ removeCustomPortalDomain(data: {
324
+ domain: string;
325
+ }): Promise<Rec>;
326
+ generatePortalOnboardLink(data: {
327
+ email: string;
328
+ name?: string;
329
+ expiresInHours?: number;
330
+ workspaceId?: string;
331
+ }): Promise<Rec>;
332
+ lookupTaxIdViaVIES(data: {
333
+ vatNumber: string;
334
+ countryCode: string;
335
+ }): Promise<Rec>;
336
+ getIgicModeloSummary(modeloCode: string, params?: {
337
+ year?: string;
338
+ period?: string;
339
+ }): Promise<Rec>;
340
+ calculateAiem(data: {
341
+ ncCode: string;
342
+ amount: number;
343
+ description?: string;
344
+ }): Promise<Rec>;
345
+ getISSummary(modeloCode: string, params?: {
346
+ year?: string;
347
+ installment?: string;
348
+ }): Promise<Rec>;
349
+ listBankRules(params?: {
350
+ limit?: number;
351
+ offset?: number;
352
+ }): Promise<PaginatedResponse<Rec>>;
353
+ createBankRule(data: {
354
+ name: string;
355
+ conditions: Array<{
356
+ field: string;
357
+ operator: string;
358
+ value: string;
359
+ }>;
360
+ actions: Array<{
361
+ type: string;
362
+ value: string;
363
+ }>;
364
+ isActive?: boolean;
365
+ }): Promise<Rec>;
366
+ sendGestoriaMessage(data: {
367
+ workspaceId: string;
368
+ parentType: "documentRequest" | "filingItem" | "obligation";
369
+ parentId: string;
370
+ body: string;
371
+ }): Promise<Rec>;
372
+ listGestoriaMessages(_params: {
373
+ workspaceId: string;
374
+ parentType: "documentRequest" | "filingItem" | "obligation";
375
+ parentId: string;
376
+ limit?: number;
377
+ before?: string;
378
+ }): Promise<{
379
+ messages: Array<Rec>;
380
+ hasMore: boolean;
381
+ }>;
382
+ createGestoriaTemplate(data: {
383
+ name: string;
384
+ title: string;
385
+ description: string;
386
+ dueDateOffsetDays: number;
387
+ attachmentRequired?: boolean;
388
+ variables?: Array<{
389
+ key: string;
390
+ label?: string;
391
+ defaultValue?: string;
392
+ }>;
393
+ }): Promise<{
394
+ templateId: string;
395
+ }>;
396
+ bulkSendGestoriaTemplate(data: {
397
+ templateId: string;
398
+ clientWorkspaceIds: string[];
399
+ periodOverrides?: {
400
+ quarter?: string | number;
401
+ year?: string | number;
402
+ month?: string | number;
403
+ };
404
+ }): Promise<Rec>;
405
+ getGestoriaAgingConsolidated(_params?: {
406
+ ownerUid?: string;
407
+ }): Promise<Rec>;
408
+ listLeaves(params?: {
409
+ limit?: number;
410
+ offset?: number;
411
+ }): Promise<PaginatedResponse<Rec>>;
412
+ createLeaveRequest(data: {
413
+ employeeId: string;
414
+ type: string;
415
+ startDate: string;
416
+ endDate: string;
417
+ reason?: string;
418
+ }): Promise<Rec>;
419
+ approveLeave(leaveId: string, data?: {
420
+ reason?: string;
421
+ }): Promise<Rec>;
422
+ rejectLeave(leaveId: string, data: {
423
+ reason: string;
424
+ }): Promise<Rec>;
425
+ cancelLeave(leaveId: string): Promise<Rec>;
426
+ attendanceClockIn(data: {
427
+ employeeId: string;
428
+ mood?: string;
429
+ location?: string;
430
+ }): Promise<Rec>;
431
+ attendanceClockOut(entryId: string): Promise<Rec>;
432
+ getOvertimeReport(params: {
433
+ period: string;
434
+ employeeId?: string;
435
+ }): Promise<Rec>;
436
+ listAnomalies(params?: {
437
+ limit?: number;
438
+ offset?: number;
439
+ }): Promise<PaginatedResponse<Rec>>;
440
+ testWebhook(id: string, data?: {
441
+ eventType?: string;
442
+ }): Promise<Rec>;
443
+ exportPayroll(params: {
444
+ format: "a3" | "contasol" | "sage" | "holded" | "siltra";
445
+ month: string;
446
+ }): Promise<Rec>;
447
+ getPayrollChecklist(params: {
448
+ month: string;
449
+ }): Promise<Rec>;
450
+ getOnboardingStatus(): Promise<Rec>;
451
+ setOnboardingPersona(data: {
452
+ persona: "autonomo" | "empresa" | "agencia" | "gestoria";
453
+ }): Promise<Rec>;
454
+ getPermissionsMatrix(): Promise<Rec>;
455
+ getMyPermissions(): Promise<Rec>;
456
+ getCurrentPeriod(params?: {
457
+ periodId?: string;
458
+ }): Promise<Rec>;
459
+ closePeriod(data: {
460
+ type: "monthly" | "quarterly";
461
+ }): Promise<Rec>;
462
+ reopenPeriod(data: {
463
+ periodId: string;
464
+ reason: string;
465
+ }): Promise<Rec>;
466
+ }
467
+ export {};
468
+ //# sourceMappingURL=demo-client.d.ts.map