@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 +21 -0
- package/README.md +464 -0
- package/dist/index.d.mts +2292 -0
- package/dist/index.d.ts +2292 -0
- package/dist/index.js +1755 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1748 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +71 -0
- package/src/client.ts +297 -0
- package/src/errors.ts +256 -0
- package/src/index.ts +195 -0
- package/src/resources/api-keys.ts +141 -0
- package/src/resources/auth.ts +286 -0
- package/src/resources/balance.ts +157 -0
- package/src/resources/companies.ts +224 -0
- package/src/resources/invoices.ts +246 -0
- package/src/resources/signatures.ts +245 -0
- package/src/resources/webhooks.ts +258 -0
- package/src/types/api-keys.ts +35 -0
- package/src/types/auth.ts +58 -0
- package/src/types/balance.ts +87 -0
- package/src/types/common.ts +114 -0
- package/src/types/companies.ts +86 -0
- package/src/types/index.ts +115 -0
- package/src/types/invoices.ts +191 -0
- package/src/types/signatures.ts +153 -0
- package/src/types/webhooks.ts +146 -0
- package/src/utils/retry.ts +167 -0
- package/src/utils/webhook-verify.ts +290 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scell SDK Error Classes
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ApiErrorResponse } from './types/common.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Base error class for all Scell API errors
|
|
11
|
+
*/
|
|
12
|
+
export class ScellError extends Error {
|
|
13
|
+
/** HTTP status code */
|
|
14
|
+
public readonly status: number;
|
|
15
|
+
/** Error code from API */
|
|
16
|
+
public readonly code: string | undefined;
|
|
17
|
+
/** Original response body */
|
|
18
|
+
public readonly body: unknown;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
message: string,
|
|
22
|
+
status: number,
|
|
23
|
+
code?: string,
|
|
24
|
+
body?: unknown
|
|
25
|
+
) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'ScellError';
|
|
28
|
+
this.status = status;
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.body = body;
|
|
31
|
+
|
|
32
|
+
// Maintains proper stack trace in V8 environments
|
|
33
|
+
if (Error.captureStackTrace) {
|
|
34
|
+
Error.captureStackTrace(this, this.constructor);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Error thrown when authentication fails (401)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* try {
|
|
45
|
+
* await client.invoices.list();
|
|
46
|
+
* } catch (error) {
|
|
47
|
+
* if (error instanceof ScellAuthenticationError) {
|
|
48
|
+
* console.log('Invalid or expired token');
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export class ScellAuthenticationError extends ScellError {
|
|
54
|
+
constructor(message = 'Authentication failed', body?: unknown) {
|
|
55
|
+
super(message, 401, 'AUTHENTICATION_ERROR', body);
|
|
56
|
+
this.name = 'ScellAuthenticationError';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Error thrown when authorization fails (403)
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* try {
|
|
66
|
+
* await client.admin.users();
|
|
67
|
+
* } catch (error) {
|
|
68
|
+
* if (error instanceof ScellAuthorizationError) {
|
|
69
|
+
* console.log('Insufficient permissions');
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export class ScellAuthorizationError extends ScellError {
|
|
75
|
+
constructor(message = 'Access denied', body?: unknown) {
|
|
76
|
+
super(message, 403, 'AUTHORIZATION_ERROR', body);
|
|
77
|
+
this.name = 'ScellAuthorizationError';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Error thrown when validation fails (422)
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* try {
|
|
87
|
+
* await client.invoices.create(invalidData);
|
|
88
|
+
* } catch (error) {
|
|
89
|
+
* if (error instanceof ScellValidationError) {
|
|
90
|
+
* console.log('Validation errors:', error.errors);
|
|
91
|
+
* }
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export class ScellValidationError extends ScellError {
|
|
96
|
+
/** Field-level validation errors */
|
|
97
|
+
public readonly errors: Record<string, string[]>;
|
|
98
|
+
|
|
99
|
+
constructor(
|
|
100
|
+
message: string,
|
|
101
|
+
errors: Record<string, string[]> = {},
|
|
102
|
+
body?: unknown
|
|
103
|
+
) {
|
|
104
|
+
super(message, 422, 'VALIDATION_ERROR', body);
|
|
105
|
+
this.name = 'ScellValidationError';
|
|
106
|
+
this.errors = errors;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get all error messages as a flat array
|
|
111
|
+
*/
|
|
112
|
+
getAllMessages(): string[] {
|
|
113
|
+
return Object.values(this.errors).flat();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get error messages for a specific field
|
|
118
|
+
*/
|
|
119
|
+
getFieldErrors(field: string): string[] {
|
|
120
|
+
return this.errors[field] ?? [];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Check if a specific field has errors
|
|
125
|
+
*/
|
|
126
|
+
hasFieldError(field: string): boolean {
|
|
127
|
+
const fieldErrors = this.errors[field];
|
|
128
|
+
return fieldErrors !== undefined && fieldErrors.length > 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Error thrown when rate limit is exceeded (429)
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* try {
|
|
138
|
+
* await client.invoices.create(data);
|
|
139
|
+
* } catch (error) {
|
|
140
|
+
* if (error instanceof ScellRateLimitError) {
|
|
141
|
+
* console.log(`Retry after ${error.retryAfter} seconds`);
|
|
142
|
+
* }
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export class ScellRateLimitError extends ScellError {
|
|
147
|
+
/** Seconds to wait before retrying */
|
|
148
|
+
public readonly retryAfter: number | undefined;
|
|
149
|
+
|
|
150
|
+
constructor(
|
|
151
|
+
message = 'Rate limit exceeded',
|
|
152
|
+
retryAfter?: number,
|
|
153
|
+
body?: unknown
|
|
154
|
+
) {
|
|
155
|
+
super(message, 429, 'RATE_LIMIT_EXCEEDED', body);
|
|
156
|
+
this.name = 'ScellRateLimitError';
|
|
157
|
+
this.retryAfter = retryAfter;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Error thrown when a resource is not found (404)
|
|
163
|
+
*/
|
|
164
|
+
export class ScellNotFoundError extends ScellError {
|
|
165
|
+
constructor(message = 'Resource not found', body?: unknown) {
|
|
166
|
+
super(message, 404, 'NOT_FOUND', body);
|
|
167
|
+
this.name = 'ScellNotFoundError';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Error thrown when the API returns a server error (5xx)
|
|
173
|
+
*/
|
|
174
|
+
export class ScellServerError extends ScellError {
|
|
175
|
+
constructor(
|
|
176
|
+
message = 'Internal server error',
|
|
177
|
+
status = 500,
|
|
178
|
+
body?: unknown
|
|
179
|
+
) {
|
|
180
|
+
super(message, status, 'SERVER_ERROR', body);
|
|
181
|
+
this.name = 'ScellServerError';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Error thrown when insufficient balance for an operation
|
|
187
|
+
*/
|
|
188
|
+
export class ScellInsufficientBalanceError extends ScellError {
|
|
189
|
+
constructor(message = 'Insufficient balance', body?: unknown) {
|
|
190
|
+
super(message, 402, 'INSUFFICIENT_BALANCE', body);
|
|
191
|
+
this.name = 'ScellInsufficientBalanceError';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Error thrown for network-related issues
|
|
197
|
+
*/
|
|
198
|
+
export class ScellNetworkError extends ScellError {
|
|
199
|
+
public readonly originalError: Error;
|
|
200
|
+
|
|
201
|
+
constructor(message: string, originalError: Error) {
|
|
202
|
+
super(message, 0, 'NETWORK_ERROR');
|
|
203
|
+
this.name = 'ScellNetworkError';
|
|
204
|
+
this.originalError = originalError;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Error thrown when request times out
|
|
210
|
+
*/
|
|
211
|
+
export class ScellTimeoutError extends ScellError {
|
|
212
|
+
constructor(message = 'Request timed out') {
|
|
213
|
+
super(message, 0, 'TIMEOUT');
|
|
214
|
+
this.name = 'ScellTimeoutError';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Parse API error response and throw appropriate error
|
|
220
|
+
*/
|
|
221
|
+
export function parseApiError(
|
|
222
|
+
status: number,
|
|
223
|
+
body: unknown,
|
|
224
|
+
headers?: Headers
|
|
225
|
+
): never {
|
|
226
|
+
const errorBody = body as ApiErrorResponse | undefined;
|
|
227
|
+
const message = errorBody?.message ?? 'Unknown error';
|
|
228
|
+
const errors = errorBody?.errors ?? {};
|
|
229
|
+
const code = errorBody?.code;
|
|
230
|
+
|
|
231
|
+
switch (status) {
|
|
232
|
+
case 401:
|
|
233
|
+
throw new ScellAuthenticationError(message, body);
|
|
234
|
+
case 402:
|
|
235
|
+
throw new ScellInsufficientBalanceError(message, body);
|
|
236
|
+
case 403:
|
|
237
|
+
throw new ScellAuthorizationError(message, body);
|
|
238
|
+
case 404:
|
|
239
|
+
throw new ScellNotFoundError(message, body);
|
|
240
|
+
case 422:
|
|
241
|
+
throw new ScellValidationError(message, errors, body);
|
|
242
|
+
case 429: {
|
|
243
|
+
const retryAfter = headers?.get('Retry-After');
|
|
244
|
+
throw new ScellRateLimitError(
|
|
245
|
+
message,
|
|
246
|
+
retryAfter ? parseInt(retryAfter, 10) : undefined,
|
|
247
|
+
body
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
default:
|
|
251
|
+
if (status >= 500) {
|
|
252
|
+
throw new ScellServerError(message, status, body);
|
|
253
|
+
}
|
|
254
|
+
throw new ScellError(message, status, code, body);
|
|
255
|
+
}
|
|
256
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scell.io Official TypeScript SDK
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { ScellClient, ScellApiClient, ScellAuth, ScellWebhooks } from '@scell/sdk';
|
|
9
|
+
*
|
|
10
|
+
* // Dashboard client (Bearer token)
|
|
11
|
+
* const auth = await ScellAuth.login({ email, password });
|
|
12
|
+
* const client = new ScellClient(auth.token);
|
|
13
|
+
*
|
|
14
|
+
* // API client (X-API-Key)
|
|
15
|
+
* const apiClient = new ScellApiClient('your-api-key');
|
|
16
|
+
*
|
|
17
|
+
* // Create invoice
|
|
18
|
+
* const invoice = await apiClient.invoices.create({...});
|
|
19
|
+
*
|
|
20
|
+
* // Verify webhook
|
|
21
|
+
* const isValid = await ScellWebhooks.verifySignature(payload, signature, secret);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// Client
|
|
26
|
+
import { HttpClient, type ClientConfig } from './client.js';
|
|
27
|
+
|
|
28
|
+
// Resources
|
|
29
|
+
import { ApiKeysResource } from './resources/api-keys.js';
|
|
30
|
+
import { AuthResource, ScellAuth } from './resources/auth.js';
|
|
31
|
+
import { BalanceResource } from './resources/balance.js';
|
|
32
|
+
import { CompaniesResource } from './resources/companies.js';
|
|
33
|
+
import { InvoicesResource } from './resources/invoices.js';
|
|
34
|
+
import { SignaturesResource } from './resources/signatures.js';
|
|
35
|
+
import { WebhooksResource } from './resources/webhooks.js';
|
|
36
|
+
|
|
37
|
+
// Utilities
|
|
38
|
+
import { ScellWebhooks } from './utils/webhook-verify.js';
|
|
39
|
+
import { withRetry, createRetryWrapper } from './utils/retry.js';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Scell Dashboard Client
|
|
43
|
+
*
|
|
44
|
+
* Use this client for dashboard/user operations with Bearer token authentication.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { ScellClient, ScellAuth } from '@scell/sdk';
|
|
49
|
+
*
|
|
50
|
+
* // Login first
|
|
51
|
+
* const auth = await ScellAuth.login({
|
|
52
|
+
* email: 'user@example.com',
|
|
53
|
+
* password: 'password'
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // Create client
|
|
57
|
+
* const client = new ScellClient(auth.token);
|
|
58
|
+
*
|
|
59
|
+
* // Use the client
|
|
60
|
+
* const companies = await client.companies.list();
|
|
61
|
+
* const balance = await client.balance.get();
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export class ScellClient {
|
|
65
|
+
private readonly http: HttpClient;
|
|
66
|
+
|
|
67
|
+
/** Authentication operations */
|
|
68
|
+
public readonly auth: AuthResource;
|
|
69
|
+
/** Company management */
|
|
70
|
+
public readonly companies: CompaniesResource;
|
|
71
|
+
/** API key management */
|
|
72
|
+
public readonly apiKeys: ApiKeysResource;
|
|
73
|
+
/** Balance and transactions */
|
|
74
|
+
public readonly balance: BalanceResource;
|
|
75
|
+
/** Webhook management */
|
|
76
|
+
public readonly webhooks: WebhooksResource;
|
|
77
|
+
/** Invoice listing (read-only via dashboard) */
|
|
78
|
+
public readonly invoices: InvoicesResource;
|
|
79
|
+
/** Signature listing (read-only via dashboard) */
|
|
80
|
+
public readonly signatures: SignaturesResource;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Create a new Scell Dashboard Client
|
|
84
|
+
*
|
|
85
|
+
* @param token - Bearer token from login
|
|
86
|
+
* @param config - Client configuration
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const client = new ScellClient('your-bearer-token', {
|
|
91
|
+
* baseUrl: 'https://api.scell.io/api/v1',
|
|
92
|
+
* timeout: 30000,
|
|
93
|
+
* retry: { maxRetries: 3 }
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
constructor(token: string, config: ClientConfig = {}) {
|
|
98
|
+
this.http = new HttpClient('bearer', token, config);
|
|
99
|
+
|
|
100
|
+
this.auth = new AuthResource(this.http);
|
|
101
|
+
this.companies = new CompaniesResource(this.http);
|
|
102
|
+
this.apiKeys = new ApiKeysResource(this.http);
|
|
103
|
+
this.balance = new BalanceResource(this.http);
|
|
104
|
+
this.webhooks = new WebhooksResource(this.http);
|
|
105
|
+
this.invoices = new InvoicesResource(this.http);
|
|
106
|
+
this.signatures = new SignaturesResource(this.http);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Scell API Client
|
|
112
|
+
*
|
|
113
|
+
* Use this client for external API operations with X-API-Key authentication.
|
|
114
|
+
* This is the client you'll use for creating invoices and signatures.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* import { ScellApiClient } from '@scell/sdk';
|
|
119
|
+
*
|
|
120
|
+
* const client = new ScellApiClient('your-api-key');
|
|
121
|
+
*
|
|
122
|
+
* // Create an invoice
|
|
123
|
+
* const invoice = await client.invoices.create({
|
|
124
|
+
* invoice_number: 'FACT-2024-001',
|
|
125
|
+
* direction: 'outgoing',
|
|
126
|
+
* output_format: 'facturx',
|
|
127
|
+
* // ...
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* // Create a signature request
|
|
131
|
+
* const signature = await client.signatures.create({
|
|
132
|
+
* title: 'Contract',
|
|
133
|
+
* document: btoa(pdfContent),
|
|
134
|
+
* document_name: 'contract.pdf',
|
|
135
|
+
* signers: [{...}]
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export class ScellApiClient {
|
|
140
|
+
private readonly http: HttpClient;
|
|
141
|
+
|
|
142
|
+
/** Invoice operations (create, download, convert) */
|
|
143
|
+
public readonly invoices: InvoicesResource;
|
|
144
|
+
/** Signature operations (create, download, remind, cancel) */
|
|
145
|
+
public readonly signatures: SignaturesResource;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Create a new Scell API Client
|
|
149
|
+
*
|
|
150
|
+
* @param apiKey - Your API key (from dashboard)
|
|
151
|
+
* @param config - Client configuration
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* // Production client
|
|
156
|
+
* const client = new ScellApiClient('sk_live_xxx');
|
|
157
|
+
*
|
|
158
|
+
* // Sandbox client
|
|
159
|
+
* const sandboxClient = new ScellApiClient('sk_test_xxx', {
|
|
160
|
+
* baseUrl: 'https://api.scell.io/api/v1/sandbox'
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
constructor(apiKey: string, config: ClientConfig = {}) {
|
|
165
|
+
this.http = new HttpClient('api-key', apiKey, config);
|
|
166
|
+
|
|
167
|
+
this.invoices = new InvoicesResource(this.http);
|
|
168
|
+
this.signatures = new SignaturesResource(this.http);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Re-export utilities
|
|
173
|
+
export { ScellAuth, ScellWebhooks, withRetry, createRetryWrapper };
|
|
174
|
+
|
|
175
|
+
// Re-export types
|
|
176
|
+
export type { ClientConfig } from './client.js';
|
|
177
|
+
export type { RetryOptions } from './utils/retry.js';
|
|
178
|
+
export type { VerifySignatureOptions } from './utils/webhook-verify.js';
|
|
179
|
+
|
|
180
|
+
// Re-export errors
|
|
181
|
+
export {
|
|
182
|
+
ScellError,
|
|
183
|
+
ScellAuthenticationError,
|
|
184
|
+
ScellAuthorizationError,
|
|
185
|
+
ScellValidationError,
|
|
186
|
+
ScellRateLimitError,
|
|
187
|
+
ScellNotFoundError,
|
|
188
|
+
ScellServerError,
|
|
189
|
+
ScellInsufficientBalanceError,
|
|
190
|
+
ScellNetworkError,
|
|
191
|
+
ScellTimeoutError,
|
|
192
|
+
} from './errors.js';
|
|
193
|
+
|
|
194
|
+
// Re-export all types
|
|
195
|
+
export * from './types/index.js';
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Keys Resource
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { HttpClient, RequestOptions } from '../client.js';
|
|
8
|
+
import type {
|
|
9
|
+
MessageResponse,
|
|
10
|
+
MessageWithDataResponse,
|
|
11
|
+
SingleResponse,
|
|
12
|
+
} from '../types/common.js';
|
|
13
|
+
import type {
|
|
14
|
+
ApiKey,
|
|
15
|
+
ApiKeyWithSecret,
|
|
16
|
+
CreateApiKeyInput,
|
|
17
|
+
} from '../types/api-keys.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* API Keys resource
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Create an API key for a company
|
|
25
|
+
* const apiKey = await client.apiKeys.create({
|
|
26
|
+
* name: 'Production Key',
|
|
27
|
+
* company_id: 'company-uuid',
|
|
28
|
+
* environment: 'production'
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Store the key securely!
|
|
32
|
+
* console.log('API Key:', apiKey.key);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class ApiKeysResource {
|
|
36
|
+
constructor(private readonly http: HttpClient) {}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* List all API keys
|
|
40
|
+
*
|
|
41
|
+
* @param requestOptions - Request options
|
|
42
|
+
* @returns List of API keys (without secrets)
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const { data: keys } = await client.apiKeys.list();
|
|
47
|
+
* keys.forEach(key => {
|
|
48
|
+
* console.log(`${key.name}: ${key.key_prefix}...`);
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
async list(requestOptions?: RequestOptions): Promise<{ data: ApiKey[] }> {
|
|
53
|
+
return this.http.get<{ data: ApiKey[] }>(
|
|
54
|
+
'/api-keys',
|
|
55
|
+
undefined,
|
|
56
|
+
requestOptions
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get a specific API key
|
|
62
|
+
*
|
|
63
|
+
* @param id - API Key UUID
|
|
64
|
+
* @param requestOptions - Request options
|
|
65
|
+
* @returns API key details (without secret)
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const { data: key } = await client.apiKeys.get('key-uuid');
|
|
70
|
+
* console.log(`Last used: ${key.last_used_at}`);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
async get(
|
|
74
|
+
id: string,
|
|
75
|
+
requestOptions?: RequestOptions
|
|
76
|
+
): Promise<SingleResponse<ApiKey>> {
|
|
77
|
+
return this.http.get<SingleResponse<ApiKey>>(
|
|
78
|
+
`/api-keys/${id}`,
|
|
79
|
+
undefined,
|
|
80
|
+
requestOptions
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Create a new API key
|
|
86
|
+
*
|
|
87
|
+
* Important: The full key is only returned once during creation.
|
|
88
|
+
* Store it securely - you won't be able to retrieve it again.
|
|
89
|
+
*
|
|
90
|
+
* @param input - API key configuration
|
|
91
|
+
* @param requestOptions - Request options
|
|
92
|
+
* @returns Created API key with full key value
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const { data: apiKey } = await client.apiKeys.create({
|
|
97
|
+
* name: 'Production Integration',
|
|
98
|
+
* company_id: 'company-uuid',
|
|
99
|
+
* environment: 'production',
|
|
100
|
+
* permissions: ['invoices:write', 'signatures:write']
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* // IMPORTANT: Store this key securely!
|
|
104
|
+
* // You won't be able to see it again.
|
|
105
|
+
* console.log('Save this key:', apiKey.key);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
async create(
|
|
109
|
+
input: CreateApiKeyInput,
|
|
110
|
+
requestOptions?: RequestOptions
|
|
111
|
+
): Promise<MessageWithDataResponse<ApiKeyWithSecret>> {
|
|
112
|
+
return this.http.post<MessageWithDataResponse<ApiKeyWithSecret>>(
|
|
113
|
+
'/api-keys',
|
|
114
|
+
input,
|
|
115
|
+
requestOptions
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Delete an API key
|
|
121
|
+
*
|
|
122
|
+
* Warning: This will immediately revoke the key and all
|
|
123
|
+
* requests using it will fail.
|
|
124
|
+
*
|
|
125
|
+
* @param id - API Key UUID
|
|
126
|
+
* @param requestOptions - Request options
|
|
127
|
+
* @returns Deletion confirmation
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* await client.apiKeys.delete('key-uuid');
|
|
132
|
+
* console.log('API key revoked');
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
async delete(
|
|
136
|
+
id: string,
|
|
137
|
+
requestOptions?: RequestOptions
|
|
138
|
+
): Promise<MessageResponse> {
|
|
139
|
+
return this.http.delete<MessageResponse>(`/api-keys/${id}`, requestOptions);
|
|
140
|
+
}
|
|
141
|
+
}
|