@getmandato/sdk 0.1.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.
@@ -0,0 +1,486 @@
1
+ /** Configuration options for the Mandato SDK client */
2
+ interface MandatoConfig {
3
+ /** API key (sk_live_xxx or sk_test_xxx) */
4
+ apiKey: string;
5
+ /** Base URL for the API (default: https://api.getmandato.dev) */
6
+ baseUrl?: string;
7
+ /** Request timeout in milliseconds (default: 30000) */
8
+ timeout?: number;
9
+ /** Maximum number of retries for 429/5xx errors (default: 3) */
10
+ maxRetries?: number;
11
+ }
12
+
13
+ /**
14
+ * Base HTTP client for the Mandato SDK.
15
+ * Handles auth, retries, timeouts, idempotency keys, and error mapping.
16
+ */
17
+
18
+ /** HTTP client for making requests to the Mandato API */
19
+ declare class MandatoHttpClient {
20
+ private readonly apiKey;
21
+ private readonly baseUrl;
22
+ private readonly timeout;
23
+ private readonly maxRetries;
24
+ constructor(config: MandatoConfig);
25
+ /** Make a GET request */
26
+ get<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
27
+ /** Make a POST request */
28
+ post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
29
+ /** Make a PATCH request */
30
+ patch<T>(path: string, body?: unknown): Promise<T>;
31
+ /** Make a DELETE request */
32
+ delete<T>(path: string): Promise<T>;
33
+ /** Build full URL with optional query params */
34
+ private buildUrl;
35
+ /** Execute an HTTP request with retries and error mapping */
36
+ private request;
37
+ /** Safely parse error response body */
38
+ private parseErrorBody;
39
+ }
40
+
41
+ /**
42
+ * Mandato SDK types — standalone, zero workspace dependencies.
43
+ * These mirror the API response shapes.
44
+ */
45
+ /** ISO 3166-1 alpha-2 country code */
46
+ type CountryCode = "RO" | "IT" | "BE" | "PL" | "FR" | "DE";
47
+ /** Invoice type */
48
+ type InvoiceType = "invoice" | "credit_note" | "debit_note";
49
+ /** Invoice lifecycle status */
50
+ type InvoiceStatus = "created" | "validated" | "converting" | "submitting" | "submitted" | "accepted" | "rejected" | "error";
51
+ /** Connection status */
52
+ type ConnectionStatus = "pending_setup" | "active" | "expired" | "error";
53
+ /** API key environment */
54
+ type ApiKeyEnvironment = "test" | "production";
55
+ /** Webhook event types */
56
+ type WebhookEventType = "invoice.created" | "invoice.validated" | "invoice.submitted" | "invoice.accepted" | "invoice.rejected" | "invoice.error" | "connection.active" | "connection.expired";
57
+ /** Address in a party (supplier/customer) */
58
+ interface Address {
59
+ street?: string;
60
+ city?: string;
61
+ postalCode?: string;
62
+ country: string;
63
+ stateOrProvince?: string;
64
+ }
65
+ /** Invoice party (supplier or customer) */
66
+ interface Party {
67
+ vatNumber: string;
68
+ name: string;
69
+ address?: Address;
70
+ email?: string;
71
+ phone?: string;
72
+ /** Italy SDI code (7 chars) */
73
+ sdiCode?: string;
74
+ /** Peppol participant ID */
75
+ peppolId?: string;
76
+ /** France SIRET (14 digits) */
77
+ siret?: string;
78
+ /** Germany Leitweg-ID */
79
+ leitwegId?: string;
80
+ }
81
+ /** Single invoice line item */
82
+ interface InvoiceLine {
83
+ description: string;
84
+ quantity?: number;
85
+ unitPrice: number;
86
+ vatRate: number;
87
+ unitCode?: string;
88
+ discount?: number;
89
+ itemCode?: string;
90
+ }
91
+ /** Payment details */
92
+ interface PaymentMeans {
93
+ bankAccount?: string;
94
+ bic?: string;
95
+ paymentTerms?: string;
96
+ dueDate?: string;
97
+ }
98
+ /** File attachment (base64-encoded) */
99
+ interface Attachment {
100
+ filename: string;
101
+ content: string;
102
+ mimeType: string;
103
+ }
104
+ /** Request body for creating an invoice */
105
+ interface CreateInvoiceRequest {
106
+ country: CountryCode;
107
+ invoiceType?: InvoiceType;
108
+ companyId?: string;
109
+ externalId?: string;
110
+ supplier: Party;
111
+ customer: Party;
112
+ lines: InvoiceLine[];
113
+ currency?: string;
114
+ issueDate?: string;
115
+ dueDate?: string;
116
+ note?: string;
117
+ paymentMeans?: PaymentMeans;
118
+ attachments?: Attachment[];
119
+ }
120
+ /** Request body for validating an invoice (dry-run) */
121
+ type ValidateInvoiceRequest = CreateInvoiceRequest;
122
+ /** Request body for creating a company */
123
+ interface CreateCompanyRequest {
124
+ name: string;
125
+ vatNumber: string;
126
+ country: CountryCode;
127
+ registrationNumber?: string;
128
+ address?: Address;
129
+ currency?: string;
130
+ contacts?: {
131
+ email?: string;
132
+ phone?: string;
133
+ };
134
+ }
135
+ /** Request body for updating a company */
136
+ interface UpdateCompanyRequest {
137
+ name?: string;
138
+ address?: Address;
139
+ currency?: string;
140
+ contacts?: {
141
+ email?: string;
142
+ phone?: string;
143
+ };
144
+ }
145
+ /** Request body for creating a connection */
146
+ interface CreateConnectionRequest {
147
+ companyId: string;
148
+ countryCode: CountryCode;
149
+ }
150
+ /** Request body for registering a webhook */
151
+ interface CreateWebhookRequest {
152
+ url: string;
153
+ events?: WebhookEventType[];
154
+ }
155
+ /** Request body for creating an API key */
156
+ interface CreateApiKeyRequest {
157
+ name: string;
158
+ environment?: ApiKeyEnvironment;
159
+ expiresAt?: string;
160
+ }
161
+ /** Query parameters for listing invoices */
162
+ interface ListInvoicesParams {
163
+ country?: CountryCode;
164
+ status?: InvoiceStatus;
165
+ companyId?: string;
166
+ search?: string;
167
+ dateFrom?: string;
168
+ dateTo?: string;
169
+ cursor?: string;
170
+ limit?: number;
171
+ }
172
+ /** Invoice object as returned by the API */
173
+ interface Invoice {
174
+ id: string;
175
+ country: string;
176
+ supplierVat: string;
177
+ customerVat: string;
178
+ status: InvoiceStatus;
179
+ netAmount: string;
180
+ vatAmount: string;
181
+ grossAmount: string;
182
+ currency: string;
183
+ govId: string | null;
184
+ externalId: string | null;
185
+ errorMessage: string | null;
186
+ errorTranslated: string | null;
187
+ errorFix: string | null;
188
+ createdAt: string;
189
+ updatedAt: string;
190
+ }
191
+ /** Invoice event in the timeline */
192
+ interface InvoiceEvent {
193
+ id: string;
194
+ event: string;
195
+ status: string;
196
+ metadata: Record<string, unknown> | null;
197
+ createdAt: string;
198
+ }
199
+ /** Company object as returned by the API */
200
+ interface Company {
201
+ id: string;
202
+ name: string;
203
+ vatNumber: string;
204
+ country: string;
205
+ currency: string;
206
+ isActive: boolean;
207
+ createdAt: string;
208
+ }
209
+ /** Connection object as returned by the API */
210
+ interface Connection {
211
+ id: string;
212
+ companyId: string;
213
+ countryCode: string;
214
+ status: ConnectionStatus;
215
+ tokenExpiresAt: string | null;
216
+ lastErrorMessage: string | null;
217
+ createdAt: string;
218
+ /** OAuth URL to redirect user (returned on creation for RO) */
219
+ authorizationUrl?: string;
220
+ }
221
+ /** API key object as returned by the API (masked) */
222
+ interface ApiKey {
223
+ id: string;
224
+ name: string;
225
+ keyPrefix: string;
226
+ environment: ApiKeyEnvironment;
227
+ lastUsedAt: string | null;
228
+ expiresAt: string | null;
229
+ revokedAt: string | null;
230
+ createdAt: string;
231
+ }
232
+ /** API key creation response (full key shown once) */
233
+ interface ApiKeyCreated {
234
+ id: string;
235
+ key: string;
236
+ keyPrefix: string;
237
+ name: string;
238
+ environment: ApiKeyEnvironment;
239
+ expiresAt: string | null;
240
+ createdAt: string;
241
+ }
242
+ /** Webhook configuration object */
243
+ interface WebhookConfig {
244
+ url: string | null;
245
+ secret: string | null;
246
+ events: WebhookEventType[] | null;
247
+ }
248
+ /** Webhook creation response (secret shown once) */
249
+ interface WebhookCreated {
250
+ url: string;
251
+ secret: string;
252
+ events: WebhookEventType[];
253
+ }
254
+ /** Validation result */
255
+ interface ValidationResult {
256
+ valid: boolean;
257
+ errors: string[];
258
+ }
259
+ /** Health check response */
260
+ interface HealthStatus {
261
+ status: "ok" | "degraded";
262
+ timestamp: string;
263
+ checks: {
264
+ database: string;
265
+ redis: string;
266
+ };
267
+ }
268
+ /** Paginated response wrapper */
269
+ interface PaginatedResponse<T> {
270
+ data: T[];
271
+ hasMore: boolean;
272
+ nextCursor: string | null;
273
+ }
274
+ /** Single item response wrapper */
275
+ interface SingleResponse<T> {
276
+ data: T;
277
+ }
278
+ /** Deletion confirmation */
279
+ interface DeletedResponse {
280
+ data: {
281
+ id: string;
282
+ deleted: boolean;
283
+ };
284
+ }
285
+
286
+ /** API key resource operations */
287
+ declare class ApiKeys {
288
+ private readonly http;
289
+ constructor(http: MandatoHttpClient);
290
+ /** List API keys (masked) */
291
+ list(): Promise<SingleResponse<ApiKey[]>>;
292
+ /** Create a new API key (full key returned once) */
293
+ create(data: CreateApiKeyRequest): Promise<SingleResponse<ApiKeyCreated>>;
294
+ /** Revoke an API key */
295
+ revoke(id: string): Promise<SingleResponse<{
296
+ id: string;
297
+ revoked: boolean;
298
+ }>>;
299
+ }
300
+
301
+ /** Company resource operations */
302
+ declare class Companies {
303
+ private readonly http;
304
+ constructor(http: MandatoHttpClient);
305
+ /** Create a company */
306
+ create(data: CreateCompanyRequest): Promise<SingleResponse<Company>>;
307
+ /** List all companies */
308
+ list(): Promise<SingleResponse<Company[]>>;
309
+ /** Get a single company by ID */
310
+ get(id: string): Promise<SingleResponse<Company>>;
311
+ /** Update a company */
312
+ update(id: string, data: UpdateCompanyRequest): Promise<SingleResponse<Company>>;
313
+ /** Delete a company */
314
+ delete(id: string): Promise<DeletedResponse>;
315
+ }
316
+
317
+ /** Connection resource operations */
318
+ declare class Connections {
319
+ private readonly http;
320
+ constructor(http: MandatoHttpClient);
321
+ /** Initialize a government connection */
322
+ create(data: CreateConnectionRequest): Promise<SingleResponse<Connection>>;
323
+ /** List all connections */
324
+ list(): Promise<SingleResponse<Connection[]>>;
325
+ /** Get a single connection by ID */
326
+ get(id: string): Promise<SingleResponse<Connection>>;
327
+ /** Remove a connection */
328
+ delete(id: string): Promise<DeletedResponse>;
329
+ }
330
+
331
+ /** Invoice resource operations */
332
+ declare class Invoices {
333
+ private readonly http;
334
+ constructor(http: MandatoHttpClient);
335
+ /** Create and submit an invoice */
336
+ create(data: CreateInvoiceRequest, idempotencyKey?: string): Promise<SingleResponse<Invoice>>;
337
+ /** List invoices with optional filters */
338
+ list(params?: ListInvoicesParams): Promise<PaginatedResponse<Invoice>>;
339
+ /** Get a single invoice by ID */
340
+ get(id: string): Promise<SingleResponse<Invoice>>;
341
+ /** Dry-run validation without submission */
342
+ validate(data: ValidateInvoiceRequest): Promise<ValidationResult>;
343
+ /** Get invoice event timeline */
344
+ getEvents(id: string): Promise<SingleResponse<InvoiceEvent[]>>;
345
+ }
346
+
347
+ /** Webhook resource operations */
348
+ declare class Webhooks {
349
+ private readonly http;
350
+ constructor(http: MandatoHttpClient);
351
+ /** Register a webhook URL */
352
+ create(data: CreateWebhookRequest): Promise<SingleResponse<WebhookCreated>>;
353
+ /** Get current webhook configuration */
354
+ get(): Promise<SingleResponse<WebhookConfig>>;
355
+ /** Remove webhook */
356
+ delete(): Promise<SingleResponse<{
357
+ deleted: boolean;
358
+ }>>;
359
+ }
360
+
361
+ /**
362
+ * Main Mandato SDK client.
363
+ * Composes all resource namespaces for a clean, typed API.
364
+ */
365
+
366
+ /**
367
+ * The Mandato SDK client.
368
+ *
369
+ * @example
370
+ * ```typescript
371
+ * import { MandatoClient } from "@getmandato/sdk";
372
+ *
373
+ * const mandato = new MandatoClient({ apiKey: "sk_live_xxx" });
374
+ *
375
+ * const { data: invoice } = await mandato.invoices.create({
376
+ * country: "RO",
377
+ * supplier: { vatNumber: "RO12345678", name: "Supplier SRL" },
378
+ * customer: { vatNumber: "RO87654321", name: "Customer SRL" },
379
+ * lines: [{ description: "Consulting", unitPrice: 100, vatRate: 19 }],
380
+ * });
381
+ * ```
382
+ */
383
+ declare class MandatoClient {
384
+ /** Invoice operations */
385
+ readonly invoices: Invoices;
386
+ /** Company operations */
387
+ readonly companies: Companies;
388
+ /** Connection operations */
389
+ readonly connections: Connections;
390
+ /** Webhook operations */
391
+ readonly webhooks: Webhooks;
392
+ /** API key operations */
393
+ readonly apiKeys: ApiKeys;
394
+ private readonly http;
395
+ constructor(config: MandatoConfig);
396
+ /** Check API health */
397
+ health(): Promise<HealthStatus>;
398
+ }
399
+
400
+ /**
401
+ * Mandato SDK error classes.
402
+ * Map HTTP status codes to typed errors for developer-friendly handling.
403
+ */
404
+ /** Base error for all Mandato API errors */
405
+ declare class MandatoError extends Error {
406
+ /** HTTP status code */
407
+ readonly status: number;
408
+ /** Error type from the API response */
409
+ readonly type: string;
410
+ /** Request ID for support reference */
411
+ readonly requestId?: string;
412
+ constructor(message: string, status: number, type: string, requestId?: string);
413
+ }
414
+ /** 400 — Request validation failed */
415
+ declare class ValidationError extends MandatoError {
416
+ readonly details: Array<{
417
+ path: string;
418
+ message: string;
419
+ }>;
420
+ constructor(message: string, details?: Array<{
421
+ path: string;
422
+ message: string;
423
+ }>, requestId?: string);
424
+ }
425
+ /** 401 — Invalid or missing API key */
426
+ declare class AuthenticationError extends MandatoError {
427
+ constructor(message?: string, requestId?: string);
428
+ }
429
+ /** 403 — Insufficient permissions or plan limit */
430
+ declare class ForbiddenError extends MandatoError {
431
+ constructor(message?: string, requestId?: string);
432
+ }
433
+ /** 404 — Resource not found */
434
+ declare class NotFoundError extends MandatoError {
435
+ constructor(message?: string, requestId?: string);
436
+ }
437
+ /** 409 — Idempotency conflict */
438
+ declare class ConflictError extends MandatoError {
439
+ constructor(message?: string, requestId?: string);
440
+ }
441
+ /** 429 — Rate limit exceeded */
442
+ declare class RateLimitError extends MandatoError {
443
+ /** Requests per minute allowed */
444
+ readonly limit?: number;
445
+ /** Seconds until the rate limit resets */
446
+ readonly retryAfter?: number;
447
+ constructor(message: string, limit?: number, retryAfter?: number, requestId?: string);
448
+ }
449
+ /** 500+ — Server-side error */
450
+ declare class ServerError extends MandatoError {
451
+ constructor(message?: string, status?: number, requestId?: string);
452
+ }
453
+
454
+ /**
455
+ * Webhook signature verification and event construction.
456
+ * Uses HMAC-SHA256 with timing-safe comparison.
457
+ */
458
+ /** Webhook event payload as delivered by Mandato */
459
+ interface WebhookEvent {
460
+ id: string;
461
+ type: string;
462
+ createdAt: string;
463
+ data: Record<string, unknown>;
464
+ }
465
+ /**
466
+ * Verify a webhook signature against the payload.
467
+ * Uses HMAC-SHA256 with timing-safe comparison to prevent timing attacks.
468
+ *
469
+ * @param payload — raw request body string
470
+ * @param signature — value of the X-Mandato-Signature header
471
+ * @param secret — webhook signing secret from the dashboard
472
+ * @returns true if the signature is valid
473
+ */
474
+ declare function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean;
475
+ /**
476
+ * Verify the webhook signature and parse the event payload.
477
+ * Throws if the signature is invalid.
478
+ *
479
+ * @param payload — raw request body string
480
+ * @param signature — value of the X-Mandato-Signature header
481
+ * @param secret — webhook signing secret from the dashboard
482
+ * @returns parsed WebhookEvent
483
+ */
484
+ declare function constructWebhookEvent(payload: string, signature: string, secret: string): WebhookEvent;
485
+
486
+ export { type Address, type ApiKey, type ApiKeyCreated, type ApiKeyEnvironment, type Attachment, AuthenticationError, type Company, ConflictError, type Connection, type ConnectionStatus, type CountryCode, type CreateApiKeyRequest, type CreateCompanyRequest, type CreateConnectionRequest, type CreateInvoiceRequest, type CreateWebhookRequest, type DeletedResponse, ForbiddenError, type HealthStatus, type Invoice, type InvoiceEvent, type InvoiceLine, type InvoiceStatus, type InvoiceType, type ListInvoicesParams, MandatoClient, type MandatoConfig, MandatoError, MandatoHttpClient, NotFoundError, type PaginatedResponse, type Party, type PaymentMeans, RateLimitError, ServerError, type SingleResponse, type UpdateCompanyRequest, type ValidateInvoiceRequest, ValidationError, type ValidationResult, type WebhookConfig, type WebhookCreated, type WebhookEvent, type WebhookEventType, constructWebhookEvent, verifyWebhookSignature };