@scell/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Scell.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,464 @@
1
+ # @scell/sdk
2
+
3
+ Official TypeScript SDK for [Scell.io](https://scell.io) - Electronic invoicing (Factur-X/UBL/CII) and eIDAS-compliant electronic signatures API.
4
+
5
+ ## Features
6
+
7
+ - Full TypeScript support with strict types
8
+ - Two authentication modes: Bearer token (dashboard) and API key (external API)
9
+ - Automatic retries with exponential backoff and jitter
10
+ - Webhook signature verification
11
+ - Zero external dependencies (uses native fetch)
12
+ - ESM and CommonJS support
13
+ - Node.js 18+ and browser compatible
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @scell/sdk
19
+ # or
20
+ yarn add @scell/sdk
21
+ # or
22
+ pnpm add @scell/sdk
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Authentication
28
+
29
+ ```typescript
30
+ import { ScellClient, ScellApiClient, ScellAuth } from '@scell/sdk';
31
+
32
+ // 1. Login to get a token
33
+ const auth = await ScellAuth.login({
34
+ email: 'user@example.com',
35
+ password: 'your-password',
36
+ });
37
+
38
+ // 2. Dashboard operations (Bearer token)
39
+ const client = new ScellClient(auth.token);
40
+
41
+ // 3. API operations (X-API-Key)
42
+ const apiClient = new ScellApiClient('your-api-key');
43
+ ```
44
+
45
+ ### Create an Invoice
46
+
47
+ ```typescript
48
+ const { data: invoice } = await apiClient.invoices.create({
49
+ invoice_number: 'FACT-2024-001',
50
+ direction: 'outgoing',
51
+ output_format: 'facturx',
52
+ issue_date: '2024-01-15',
53
+ due_date: '2024-02-15',
54
+ currency: 'EUR',
55
+ total_ht: 1000.0,
56
+ total_tax: 200.0,
57
+ total_ttc: 1200.0,
58
+ seller_siret: '12345678901234',
59
+ seller_name: 'My Company SAS',
60
+ seller_address: {
61
+ line1: '1 Rue de la Paix',
62
+ postal_code: '75001',
63
+ city: 'Paris',
64
+ country: 'FR',
65
+ },
66
+ buyer_siret: '98765432109876',
67
+ buyer_name: 'Client Company',
68
+ buyer_address: {
69
+ line1: '2 Avenue des Champs',
70
+ postal_code: '75008',
71
+ city: 'Paris',
72
+ country: 'FR',
73
+ },
74
+ lines: [
75
+ {
76
+ description: 'Consulting services - January 2024',
77
+ quantity: 10,
78
+ unit_price: 100.0,
79
+ tax_rate: 20.0,
80
+ total_ht: 1000.0,
81
+ total_tax: 200.0,
82
+ total_ttc: 1200.0,
83
+ },
84
+ ],
85
+ });
86
+
87
+ console.log('Invoice created:', invoice.id);
88
+ ```
89
+
90
+ ### Create a Signature Request
91
+
92
+ ```typescript
93
+ import { readFileSync } from 'fs';
94
+
95
+ const pdfContent = readFileSync('contract.pdf');
96
+
97
+ const { data: signature } = await apiClient.signatures.create({
98
+ title: 'Service Agreement 2024',
99
+ description: 'Annual service contract',
100
+ document: pdfContent.toString('base64'),
101
+ document_name: 'contract.pdf',
102
+ signers: [
103
+ {
104
+ first_name: 'John',
105
+ last_name: 'Doe',
106
+ email: 'john.doe@example.com',
107
+ auth_method: 'email',
108
+ },
109
+ {
110
+ first_name: 'Jane',
111
+ last_name: 'Smith',
112
+ phone: '+33612345678',
113
+ auth_method: 'sms',
114
+ },
115
+ ],
116
+ ui_config: {
117
+ logo_url: 'https://mycompany.com/logo.png',
118
+ primary_color: '#3b82f6',
119
+ company_name: 'My Company',
120
+ },
121
+ redirect_complete_url: 'https://myapp.com/signed',
122
+ redirect_cancel_url: 'https://myapp.com/cancelled',
123
+ });
124
+
125
+ // Send signing URLs to signers
126
+ signature.signers?.forEach((signer) => {
127
+ console.log(`${signer.email}: ${signer.signing_url}`);
128
+ });
129
+ ```
130
+
131
+ ### Webhook Verification
132
+
133
+ ```typescript
134
+ import { ScellWebhooks } from '@scell/sdk';
135
+
136
+ // Express.js example
137
+ app.post('/webhooks/scell', async (req, res) => {
138
+ const signature = req.headers['x-scell-signature'] as string;
139
+ const payload = JSON.stringify(req.body);
140
+
141
+ // Verify the webhook signature
142
+ const isValid = await ScellWebhooks.verifySignature(
143
+ payload,
144
+ signature,
145
+ process.env.WEBHOOK_SECRET!
146
+ );
147
+
148
+ if (!isValid) {
149
+ return res.status(401).send('Invalid signature');
150
+ }
151
+
152
+ // Parse and handle the event
153
+ const event = ScellWebhooks.parsePayload(payload);
154
+
155
+ switch (event.event) {
156
+ case 'invoice.validated':
157
+ console.log('Invoice validated:', event.data);
158
+ break;
159
+ case 'signature.completed':
160
+ console.log('Signature completed:', event.data);
161
+ break;
162
+ case 'balance.low':
163
+ console.log('Low balance alert!');
164
+ break;
165
+ }
166
+
167
+ res.status(200).send('OK');
168
+ });
169
+ ```
170
+
171
+ ## API Reference
172
+
173
+ ### ScellClient (Dashboard)
174
+
175
+ For user/dashboard operations with Bearer token authentication.
176
+
177
+ ```typescript
178
+ const client = new ScellClient(token, {
179
+ baseUrl: 'https://api.scell.io/api/v1', // optional
180
+ timeout: 30000, // optional, in ms
181
+ retry: { maxRetries: 3 }, // optional
182
+ });
183
+
184
+ // Resources
185
+ client.auth // User authentication
186
+ client.companies // Company management
187
+ client.apiKeys // API key management
188
+ client.balance // Balance and transactions
189
+ client.webhooks // Webhook management
190
+ client.invoices // Invoice listing (read-only)
191
+ client.signatures // Signature listing (read-only)
192
+ ```
193
+
194
+ ### ScellApiClient (External API)
195
+
196
+ For creating invoices and signatures with X-API-Key authentication.
197
+
198
+ ```typescript
199
+ const apiClient = new ScellApiClient(apiKey, {
200
+ baseUrl: 'https://api.scell.io/api/v1', // optional
201
+ timeout: 30000, // optional
202
+ });
203
+
204
+ // Resources
205
+ apiClient.invoices // Create, download, convert invoices
206
+ apiClient.signatures // Create, download, remind, cancel signatures
207
+ ```
208
+
209
+ ### Companies
210
+
211
+ ```typescript
212
+ // List companies
213
+ const { data: companies } = await client.companies.list();
214
+
215
+ // Create company
216
+ const { data: company } = await client.companies.create({
217
+ name: 'My Company',
218
+ siret: '12345678901234',
219
+ address_line1: '1 Rue Example',
220
+ postal_code: '75001',
221
+ city: 'Paris',
222
+ });
223
+
224
+ // Update company
225
+ await client.companies.update(companyId, { email: 'new@example.com' });
226
+
227
+ // Delete company
228
+ await client.companies.delete(companyId);
229
+
230
+ // KYC
231
+ const kyc = await client.companies.initiateKyc(companyId);
232
+ const status = await client.companies.kycStatus(companyId);
233
+ ```
234
+
235
+ ### Invoices
236
+
237
+ ```typescript
238
+ // List invoices (dashboard)
239
+ const { data, meta } = await client.invoices.list({
240
+ direction: 'outgoing',
241
+ status: 'validated',
242
+ from: '2024-01-01',
243
+ per_page: 50,
244
+ });
245
+
246
+ // Get invoice
247
+ const { data: invoice } = await client.invoices.get(invoiceId);
248
+
249
+ // Create invoice (API key required)
250
+ const { data: newInvoice } = await apiClient.invoices.create({...});
251
+
252
+ // Download
253
+ const { url, expires_at } = await apiClient.invoices.download(invoiceId, 'pdf');
254
+
255
+ // Audit trail
256
+ const { data: trail, integrity_valid } = await apiClient.invoices.auditTrail(invoiceId);
257
+
258
+ // Convert format
259
+ await apiClient.invoices.convert({ invoice_id: invoiceId, target_format: 'ubl' });
260
+ ```
261
+
262
+ ### Signatures
263
+
264
+ ```typescript
265
+ // List signatures (dashboard)
266
+ const { data, meta } = await client.signatures.list({
267
+ status: 'pending',
268
+ per_page: 25,
269
+ });
270
+
271
+ // Get signature
272
+ const { data: signature } = await client.signatures.get(signatureId);
273
+
274
+ // Create signature (API key required)
275
+ const { data: newSignature } = await apiClient.signatures.create({...});
276
+
277
+ // Download files
278
+ const { url: signedUrl } = await apiClient.signatures.download(signatureId, 'signed');
279
+ const { url: auditUrl } = await apiClient.signatures.download(signatureId, 'audit_trail');
280
+
281
+ // Send reminder
282
+ const { signers_reminded } = await apiClient.signatures.remind(signatureId);
283
+
284
+ // Cancel
285
+ await apiClient.signatures.cancel(signatureId);
286
+ ```
287
+
288
+ ### Balance
289
+
290
+ ```typescript
291
+ // Get balance
292
+ const { data: balance } = await client.balance.get();
293
+ console.log(`${balance.amount} ${balance.currency}`);
294
+
295
+ // Reload balance
296
+ const { transaction } = await client.balance.reload({ amount: 100 });
297
+
298
+ // Update settings
299
+ await client.balance.updateSettings({
300
+ auto_reload_enabled: true,
301
+ auto_reload_threshold: 50,
302
+ auto_reload_amount: 200,
303
+ low_balance_alert_threshold: 100,
304
+ });
305
+
306
+ // List transactions
307
+ const { data: transactions } = await client.balance.transactions({
308
+ type: 'debit',
309
+ service: 'invoice',
310
+ from: '2024-01-01',
311
+ });
312
+ ```
313
+
314
+ ### Webhooks
315
+
316
+ ```typescript
317
+ // List webhooks
318
+ const { data: webhooks } = await client.webhooks.list();
319
+
320
+ // Create webhook
321
+ const { data: webhook } = await client.webhooks.create({
322
+ url: 'https://myapp.com/webhooks/scell',
323
+ events: ['invoice.validated', 'signature.completed', 'balance.low'],
324
+ environment: 'production',
325
+ });
326
+ // IMPORTANT: Store webhook.secret securely!
327
+
328
+ // Update webhook
329
+ await client.webhooks.update(webhookId, { is_active: false });
330
+
331
+ // Test webhook
332
+ const result = await client.webhooks.test(webhookId);
333
+ console.log('Test successful:', result.success);
334
+
335
+ // Regenerate secret
336
+ const { data: updated } = await client.webhooks.regenerateSecret(webhookId);
337
+ // Update your stored secret!
338
+
339
+ // View logs
340
+ const { data: logs } = await client.webhooks.logs(webhookId);
341
+
342
+ // Delete webhook
343
+ await client.webhooks.delete(webhookId);
344
+ ```
345
+
346
+ ## Error Handling
347
+
348
+ ```typescript
349
+ import {
350
+ ScellError,
351
+ ScellAuthenticationError,
352
+ ScellValidationError,
353
+ ScellRateLimitError,
354
+ ScellNotFoundError,
355
+ ScellInsufficientBalanceError,
356
+ } from '@scell/sdk';
357
+
358
+ try {
359
+ await apiClient.invoices.create(data);
360
+ } catch (error) {
361
+ if (error instanceof ScellValidationError) {
362
+ console.log('Validation errors:', error.errors);
363
+ error.getAllMessages().forEach(msg => console.log(msg));
364
+ } else if (error instanceof ScellAuthenticationError) {
365
+ console.log('Invalid credentials');
366
+ } else if (error instanceof ScellRateLimitError) {
367
+ console.log(`Rate limited. Retry after ${error.retryAfter}s`);
368
+ } else if (error instanceof ScellInsufficientBalanceError) {
369
+ console.log('Insufficient balance, please reload');
370
+ } else if (error instanceof ScellNotFoundError) {
371
+ console.log('Resource not found');
372
+ } else if (error instanceof ScellError) {
373
+ console.log(`API error: ${error.message} (${error.status})`);
374
+ }
375
+ }
376
+ ```
377
+
378
+ ## Retry Configuration
379
+
380
+ The SDK automatically retries failed requests for rate limits (429) and server errors (5xx).
381
+
382
+ ```typescript
383
+ import { withRetry, createRetryWrapper } from '@scell/sdk';
384
+
385
+ // Custom retry options
386
+ const client = new ScellClient(token, {
387
+ retry: {
388
+ maxRetries: 5,
389
+ baseDelay: 1000,
390
+ maxDelay: 30000,
391
+ jitterFactor: 0.1,
392
+ },
393
+ });
394
+
395
+ // Disable retry for specific request
396
+ const result = await client.companies.list({ skipRetry: true });
397
+
398
+ // Manual retry wrapper
399
+ const result = await withRetry(
400
+ () => apiClient.invoices.create(data),
401
+ { maxRetries: 5 }
402
+ );
403
+ ```
404
+
405
+ ## Webhook Events
406
+
407
+ | Event | Description |
408
+ |-------|-------------|
409
+ | `invoice.created` | Invoice created |
410
+ | `invoice.validated` | Invoice validated |
411
+ | `invoice.transmitted` | Invoice transmitted to recipient |
412
+ | `invoice.accepted` | Invoice accepted |
413
+ | `invoice.rejected` | Invoice rejected |
414
+ | `invoice.error` | Invoice processing error |
415
+ | `signature.created` | Signature request created |
416
+ | `signature.waiting` | Waiting for signers |
417
+ | `signature.signed` | A signer has signed |
418
+ | `signature.completed` | All signers have signed |
419
+ | `signature.refused` | Signature refused |
420
+ | `signature.expired` | Signature expired |
421
+ | `signature.error` | Signature processing error |
422
+ | `balance.low` | Balance below low threshold |
423
+ | `balance.critical` | Balance below critical threshold |
424
+
425
+ ## TypeScript Types
426
+
427
+ All types are exported and can be imported:
428
+
429
+ ```typescript
430
+ import type {
431
+ Invoice,
432
+ InvoiceStatus,
433
+ InvoiceDirection,
434
+ CreateInvoiceInput,
435
+ Signature,
436
+ SignatureStatus,
437
+ CreateSignatureInput,
438
+ Signer,
439
+ Company,
440
+ Balance,
441
+ Transaction,
442
+ Webhook,
443
+ WebhookEvent,
444
+ WebhookPayload,
445
+ } from '@scell/sdk';
446
+ ```
447
+
448
+ ## Environment Variables
449
+
450
+ ```bash
451
+ # API Configuration
452
+ SCELL_API_URL=https://api.scell.io/api/v1
453
+ SCELL_API_KEY=your-api-key
454
+ SCELL_WEBHOOK_SECRET=whsec_your-webhook-secret
455
+ ```
456
+
457
+ ## Requirements
458
+
459
+ - Node.js 18.0.0 or higher (for native fetch)
460
+ - TypeScript 5.0 or higher (for development)
461
+
462
+ ## License
463
+
464
+ MIT