keycae-ts 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/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # keycae-ts 🚀
2
+
3
+ Cliente SDK oficial en **TypeScript** y **JavaScript** para interactuar con la plataforma de **KeyCAE.ar** y emitir facturación electrónica oficial homologada ante **ARCA (ex AFIP)** de forma simple y resiliente.
4
+
5
+ ## Instalación
6
+
7
+ Instala el SDK en tu proyecto Node.js/TypeScript:
8
+
9
+ ```bash
10
+ npm install keycae-ts
11
+ # O usando yarn / pnpm
12
+ yarn add keycae-ts
13
+ pnpm add keycae-ts
14
+ ```
15
+
16
+ ## Inicio Rápido (Modelo A: Delegación Directa ⭐)
17
+
18
+ Esta es la forma recomendada por defecto. En minutos podés facturar sin lidiar con llaves privadas o subir archivos de certificados.
19
+
20
+ ```typescript
21
+ import { KeyCaeClient } from 'keycae-ts';
22
+
23
+ // 1. Inicializar el cliente con tu API Key
24
+ const client = new KeyCaeClient('sk_test_tu_api_key_aqui');
25
+
26
+ async function main() {
27
+ try {
28
+ // 2. Registrar la delegación (previamente debés adherir el servicio en el portal de ARCA al CUIT representante 20254459306)
29
+ console.log('Iniciando delegación directa...');
30
+ const delegation = await client.createDelegation({
31
+ cuit: '20254459306',
32
+ organization: 'Digital Media S.A.'
33
+ });
34
+
35
+ console.log(`Estado inicial de delegación: ${delegation.status}`);
36
+
37
+ // 3. Emitir una factura electrónica homologada (con CAE y PDF)
38
+ console.log('Emitiendo factura fiscal...');
39
+ const invoice = await client.emitInvoice({
40
+ cuit_emisor: '20254459306',
41
+ punto_de_venta: 1,
42
+ tipo_comprobante: 'C',
43
+ receptor: {
44
+ tipo_doc: 'DNI',
45
+ nro_doc: '35987654'
46
+ },
47
+ conceptos: [
48
+ {
49
+ descripcion: 'Servicios de Consultoría de Software',
50
+ precio: 150000.00
51
+ }
52
+ ]
53
+ }, 'idempotency_key_factura_42'); // Idempotency key para prevenir duplicaciones de red
54
+
55
+ console.log('¡Factura autorizada exitosamente!');
56
+ console.log(`Comprobante: Nro. ${invoice.numero_factura}`);
57
+ console.log(`CAE Otorgado: ${invoice.cae}`);
58
+ console.log(`Vencimiento CAE: ${invoice.cae_vencimiento}`);
59
+ console.log(`PDF de Impresión: ${invoice.url_pdf}`);
60
+ console.log(`Código QR Fiscal: ${invoice.url_qr}`);
61
+
62
+ } catch (error) {
63
+ console.error('Error durante la operación:', error);
64
+ }
65
+ }
66
+
67
+ main();
68
+ ```
69
+
70
+ ## Notificaciones en Tiempo Real (Telegram Alerts)
71
+
72
+ Configurá tu bot de Telegram a través de la API para recibir alertas móviles al instante de cada comprobante emitido:
73
+
74
+ ```typescript
75
+ import { KeyCaeClient } from 'keycae-ts';
76
+
77
+ const client = new KeyCaeClient('sk_test_tu_api_key_aqui');
78
+
79
+ async function setupAlerts() {
80
+ // Guardar configuración del Bot
81
+ await client.saveTelegramSettings({
82
+ telegram_bot_token: '123456789:ABCdefGhIjKlMnOpQrStUvWxYz_TOKEN',
83
+ telegram_chat_id: '987654321'
84
+ });
85
+
86
+ // Consultar configuración actual (retorna enmascarada)
87
+ const settings = await client.getTelegramSettings();
88
+ console.log('Ajustes de alertas activos:', settings);
89
+ }
90
+
91
+ setupAlerts();
92
+ ```
93
+
94
+ ## Licencia
95
+
96
+ MIT
@@ -0,0 +1,145 @@
1
+ export interface TaxpayerResponse {
2
+ cuit: string;
3
+ nombre: string;
4
+ tipo_persona: string;
5
+ categoria_monotributo?: string;
6
+ es_iva_inscripto: boolean;
7
+ estado: string;
8
+ }
9
+ export interface InvoiceReceptor {
10
+ tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
11
+ nro_doc: string;
12
+ }
13
+ export interface InvoiceItem {
14
+ descripcion: string;
15
+ precio: number;
16
+ }
17
+ export interface InvoiceInput {
18
+ cuit_emisor: string;
19
+ punto_de_venta: number;
20
+ tipo_comprobante: 'A' | 'B' | 'C' | 'M';
21
+ receptor: InvoiceReceptor;
22
+ conceptos: InvoiceItem[];
23
+ brand_logo_url?: string;
24
+ brand_color?: string;
25
+ }
26
+ export interface InvoiceResponse {
27
+ id: string;
28
+ cuit_emisor: string;
29
+ punto_de_venta: number;
30
+ tipo_comprobante: string;
31
+ numero_factura: number;
32
+ cae: string;
33
+ cae_vencimiento: string;
34
+ url_pdf: string;
35
+ url_qr: string;
36
+ total: number;
37
+ }
38
+ export interface BillingStatusResponse {
39
+ cuit: string;
40
+ plan: string;
41
+ invoicesEmitted: number;
42
+ monthlyLimit: number;
43
+ status: string;
44
+ billingPeriodStart: string;
45
+ percentageConsumed: number;
46
+ overageCost: number;
47
+ currency: string;
48
+ }
49
+ export interface TelegramSettingsInput {
50
+ telegram_bot_token: string;
51
+ telegram_chat_id: string;
52
+ }
53
+ export interface TelegramSettingsResponse {
54
+ telegram_bot_token: string;
55
+ telegram_chat_id: string;
56
+ has_credentials: boolean;
57
+ }
58
+ export interface DelegationInput {
59
+ cuit: string;
60
+ organization: string;
61
+ }
62
+ export interface DelegationResponse {
63
+ id: string;
64
+ status: 'pending' | 'accepted' | 'rejected';
65
+ cuit: string;
66
+ organization: string;
67
+ representativeCuit: string;
68
+ representativeOrg: string;
69
+ createdAt: string;
70
+ acceptedAt?: string;
71
+ }
72
+ export interface KmsCredentialInput {
73
+ cuit: string;
74
+ organization: string;
75
+ common_name?: string;
76
+ }
77
+ export interface KmsCredentialResponse {
78
+ id: string;
79
+ cuit: string;
80
+ organization: string;
81
+ common_name: string;
82
+ status: string;
83
+ csr_pem?: string;
84
+ created_at: string;
85
+ }
86
+ export interface KmsImportInput {
87
+ cuit: string;
88
+ organization: string;
89
+ certificate: string;
90
+ private_key: string;
91
+ }
92
+ export declare class KeyCaeClient {
93
+ private apiKey;
94
+ private baseUrl;
95
+ constructor(apiKey: string, baseUrl?: string);
96
+ private request;
97
+ /**
98
+ * Consultar Contribuyente en Padrón ARCA
99
+ */
100
+ getTaxpayer(cuit: string): Promise<TaxpayerResponse>;
101
+ /**
102
+ * Registrar / Iniciar Direct Delegation
103
+ */
104
+ createDelegation(data: DelegationInput): Promise<DelegationResponse>;
105
+ /**
106
+ * Consultar Estado de Delegación Directa
107
+ */
108
+ checkDelegationStatus(): Promise<DelegationResponse>;
109
+ /**
110
+ * Crear Bóveda de Claves KMS & Generar CSR
111
+ */
112
+ createCredential(data: KmsCredentialInput): Promise<KmsCredentialResponse>;
113
+ /**
114
+ * Importar Credenciales de Firma Existentes (.key y .crt)
115
+ */
116
+ importCredential(data: KmsImportInput): Promise<KmsCredentialResponse>;
117
+ /**
118
+ * Activar Bóveda KMS con Certificado ARCA (.crt)
119
+ */
120
+ activateCredential(id: string, certificatePem: string): Promise<any>;
121
+ /**
122
+ * Eliminar Bóveda de Claves KMS de forma física y segura
123
+ */
124
+ deleteCredential(id: string): Promise<any>;
125
+ /**
126
+ * Emitir Factura Electrónica Homologada (CAE)
127
+ */
128
+ emitInvoice(data: InvoiceInput, idempotencyKey?: string): Promise<InvoiceResponse>;
129
+ /**
130
+ * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
131
+ */
132
+ getInvoicePdfBuffer(id: string): Promise<Buffer>;
133
+ /**
134
+ * Obtener Consumos y Estado del Plan (Billing)
135
+ */
136
+ getBillingStatus(): Promise<BillingStatusResponse>;
137
+ /**
138
+ * Obtener Ajustes de Telegram por Tenant
139
+ */
140
+ getTelegramSettings(): Promise<TelegramSettingsResponse>;
141
+ /**
142
+ * Guardar / Actualizar Ajustes de Telegram
143
+ */
144
+ saveTelegramSettings(data: TelegramSettingsInput): Promise<any>;
145
+ }
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.KeyCaeClient = void 0;
7
+ const node_fetch_1 = __importDefault(require("node-fetch"));
8
+ class KeyCaeClient {
9
+ constructor(apiKey, baseUrl = 'https://api.keycae.ar') {
10
+ this.apiKey = apiKey;
11
+ this.baseUrl = baseUrl;
12
+ }
13
+ async request(method, path, body, idempotencyKey) {
14
+ const headers = {
15
+ 'Authorization': `Bearer ${this.apiKey}`,
16
+ 'Content-Type': 'application/json'
17
+ };
18
+ if (idempotencyKey) {
19
+ headers['Idempotency-Key'] = idempotencyKey;
20
+ }
21
+ const response = await (0, node_fetch_1.default)(`${this.baseUrl}${path}`, {
22
+ method,
23
+ headers,
24
+ body: body ? JSON.stringify(body) : undefined
25
+ });
26
+ if (!response.ok) {
27
+ let errorDetails = '';
28
+ try {
29
+ errorDetails = await response.text();
30
+ }
31
+ catch (e) { }
32
+ throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
33
+ }
34
+ return response.json();
35
+ }
36
+ /**
37
+ * Consultar Contribuyente en Padrón ARCA
38
+ */
39
+ async getTaxpayer(cuit) {
40
+ return this.request('GET', `/v1/taxpayers/${cuit}`);
41
+ }
42
+ /**
43
+ * Registrar / Iniciar Direct Delegation
44
+ */
45
+ async createDelegation(data) {
46
+ return this.request('POST', '/v1/delegations', data);
47
+ }
48
+ /**
49
+ * Consultar Estado de Delegación Directa
50
+ */
51
+ async checkDelegationStatus() {
52
+ return this.request('GET', '/v1/delegations/status');
53
+ }
54
+ /**
55
+ * Crear Bóveda de Claves KMS & Generar CSR
56
+ */
57
+ async createCredential(data) {
58
+ return this.request('POST', '/v1/credentials', data);
59
+ }
60
+ /**
61
+ * Importar Credenciales de Firma Existentes (.key y .crt)
62
+ */
63
+ async importCredential(data) {
64
+ return this.request('POST', '/v1/credentials/import', data);
65
+ }
66
+ /**
67
+ * Activar Bóveda KMS con Certificado ARCA (.crt)
68
+ */
69
+ async activateCredential(id, certificatePem) {
70
+ return this.request('POST', `/v1/credentials/${id}/certificate`, { certificate: certificatePem });
71
+ }
72
+ /**
73
+ * Eliminar Bóveda de Claves KMS de forma física y segura
74
+ */
75
+ async deleteCredential(id) {
76
+ return this.request('DELETE', `/v1/credentials/${id}`);
77
+ }
78
+ /**
79
+ * Emitir Factura Electrónica Homologada (CAE)
80
+ */
81
+ async emitInvoice(data, idempotencyKey) {
82
+ return this.request('POST', '/v1/invoices', data, idempotencyKey);
83
+ }
84
+ /**
85
+ * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
86
+ */
87
+ async getInvoicePdfBuffer(id) {
88
+ const response = await (0, node_fetch_1.default)(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
89
+ method: 'GET',
90
+ headers: {
91
+ 'Authorization': `Bearer ${this.apiKey}`
92
+ }
93
+ });
94
+ if (!response.ok) {
95
+ throw new Error(`Failed to fetch PDF (${response.status})`);
96
+ }
97
+ const arrayBuffer = await response.arrayBuffer();
98
+ return Buffer.from(arrayBuffer);
99
+ }
100
+ /**
101
+ * Obtener Consumos y Estado del Plan (Billing)
102
+ */
103
+ async getBillingStatus() {
104
+ return this.request('GET', '/v1/billing/status');
105
+ }
106
+ /**
107
+ * Obtener Ajustes de Telegram por Tenant
108
+ */
109
+ async getTelegramSettings() {
110
+ return this.request('GET', '/v1/settings/telegram');
111
+ }
112
+ /**
113
+ * Guardar / Actualizar Ajustes de Telegram
114
+ */
115
+ async saveTelegramSettings(data) {
116
+ return this.request('POST', '/v1/settings/telegram', data);
117
+ }
118
+ }
119
+ exports.KeyCaeClient = KeyCaeClient;
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "keycae-ts",
3
+ "version": "1.0.0",
4
+ "description": "Official TypeScript & JavaScript SDK client for KeyCAE.ar impositive compliance API (ARCA)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "keywords": [
12
+ "arca",
13
+ "afip",
14
+ "factura-electronica",
15
+ "compliance",
16
+ "sdk",
17
+ "client",
18
+ "keycae",
19
+ "argentina"
20
+ ],
21
+ "author": "KeyCAE Community",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "node-fetch": "^2.6.9"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^18.15.11",
28
+ "@types/node-fetch": "^2.6.3",
29
+ "typescript": "^5.0.4"
30
+ }
31
+ }
package/src/index.ts ADDED
@@ -0,0 +1,243 @@
1
+ import fetch from 'node-fetch';
2
+
3
+ export interface TaxpayerResponse {
4
+ cuit: string;
5
+ nombre: string;
6
+ tipo_persona: string;
7
+ categoria_monotributo?: string;
8
+ es_iva_inscripto: boolean;
9
+ estado: string;
10
+ }
11
+
12
+ export interface InvoiceReceptor {
13
+ tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
14
+ nro_doc: string;
15
+ }
16
+
17
+ export interface InvoiceItem {
18
+ descripcion: string;
19
+ precio: number;
20
+ }
21
+
22
+ export interface InvoiceInput {
23
+ cuit_emisor: string;
24
+ punto_de_venta: number;
25
+ tipo_comprobante: 'A' | 'B' | 'C' | 'M';
26
+ receptor: InvoiceReceptor;
27
+ conceptos: InvoiceItem[];
28
+ brand_logo_url?: string;
29
+ brand_color?: string;
30
+ }
31
+
32
+ export interface InvoiceResponse {
33
+ id: string;
34
+ cuit_emisor: string;
35
+ punto_de_venta: number;
36
+ tipo_comprobante: string;
37
+ numero_factura: number;
38
+ cae: string;
39
+ cae_vencimiento: string;
40
+ url_pdf: string;
41
+ url_qr: string;
42
+ total: number;
43
+ }
44
+
45
+ export interface BillingStatusResponse {
46
+ cuit: string;
47
+ plan: string;
48
+ invoicesEmitted: number;
49
+ monthlyLimit: number;
50
+ status: string;
51
+ billingPeriodStart: string;
52
+ percentageConsumed: number;
53
+ overageCost: number;
54
+ currency: string;
55
+ }
56
+
57
+ export interface TelegramSettingsInput {
58
+ telegram_bot_token: string;
59
+ telegram_chat_id: string;
60
+ }
61
+
62
+ export interface TelegramSettingsResponse {
63
+ telegram_bot_token: string;
64
+ telegram_chat_id: string;
65
+ has_credentials: boolean;
66
+ }
67
+
68
+ export interface DelegationInput {
69
+ cuit: string;
70
+ organization: string;
71
+ }
72
+
73
+ export interface DelegationResponse {
74
+ id: string;
75
+ status: 'pending' | 'accepted' | 'rejected';
76
+ cuit: string;
77
+ organization: string;
78
+ representativeCuit: string;
79
+ representativeOrg: string;
80
+ createdAt: string;
81
+ acceptedAt?: string;
82
+ }
83
+
84
+ export interface KmsCredentialInput {
85
+ cuit: string;
86
+ organization: string;
87
+ common_name?: string;
88
+ }
89
+
90
+ export interface KmsCredentialResponse {
91
+ id: string;
92
+ cuit: string;
93
+ organization: string;
94
+ common_name: string;
95
+ status: string;
96
+ csr_pem?: string;
97
+ created_at: string;
98
+ }
99
+
100
+ export interface KmsImportInput {
101
+ cuit: string;
102
+ organization: string;
103
+ certificate: string;
104
+ private_key: string;
105
+ }
106
+
107
+ export class KeyCaeClient {
108
+ private apiKey: string;
109
+ private baseUrl: string;
110
+
111
+ constructor(apiKey: string, baseUrl: string = 'https://api.keycae.ar') {
112
+ this.apiKey = apiKey;
113
+ this.baseUrl = baseUrl;
114
+ }
115
+
116
+ private async request<T>(
117
+ method: string,
118
+ path: string,
119
+ body?: any,
120
+ idempotencyKey?: string
121
+ ): Promise<T> {
122
+ const headers: Record<string, string> = {
123
+ 'Authorization': `Bearer ${this.apiKey}`,
124
+ 'Content-Type': 'application/json'
125
+ };
126
+
127
+ if (idempotencyKey) {
128
+ headers['Idempotency-Key'] = idempotencyKey;
129
+ }
130
+
131
+ const response = await fetch(`${this.baseUrl}${path}`, {
132
+ method,
133
+ headers,
134
+ body: body ? JSON.stringify(body) : undefined
135
+ });
136
+
137
+ if (!response.ok) {
138
+ let errorDetails = '';
139
+ try {
140
+ errorDetails = await response.text();
141
+ } catch (e) {}
142
+ throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
143
+ }
144
+
145
+ return response.json() as Promise<T>;
146
+ }
147
+
148
+ /**
149
+ * Consultar Contribuyente en Padrón ARCA
150
+ */
151
+ async getTaxpayer(cuit: string): Promise<TaxpayerResponse> {
152
+ return this.request<TaxpayerResponse>('GET', `/v1/taxpayers/${cuit}`);
153
+ }
154
+
155
+ /**
156
+ * Registrar / Iniciar Direct Delegation
157
+ */
158
+ async createDelegation(data: DelegationInput): Promise<DelegationResponse> {
159
+ return this.request<DelegationResponse>('POST', '/v1/delegations', data);
160
+ }
161
+
162
+ /**
163
+ * Consultar Estado de Delegación Directa
164
+ */
165
+ async checkDelegationStatus(): Promise<DelegationResponse> {
166
+ return this.request<DelegationResponse>('GET', '/v1/delegations/status');
167
+ }
168
+
169
+ /**
170
+ * Crear Bóveda de Claves KMS & Generar CSR
171
+ */
172
+ async createCredential(data: KmsCredentialInput): Promise<KmsCredentialResponse> {
173
+ return this.request<KmsCredentialResponse>('POST', '/v1/credentials', data);
174
+ }
175
+
176
+ /**
177
+ * Importar Credenciales de Firma Existentes (.key y .crt)
178
+ */
179
+ async importCredential(data: KmsImportInput): Promise<KmsCredentialResponse> {
180
+ return this.request<KmsCredentialResponse>('POST', '/v1/credentials/import', data);
181
+ }
182
+
183
+ /**
184
+ * Activar Bóveda KMS con Certificado ARCA (.crt)
185
+ */
186
+ async activateCredential(id: string, certificatePem: string): Promise<any> {
187
+ return this.request<any>('POST', `/v1/credentials/${id}/certificate`, { certificate: certificatePem });
188
+ }
189
+
190
+ /**
191
+ * Eliminar Bóveda de Claves KMS de forma física y segura
192
+ */
193
+ async deleteCredential(id: string): Promise<any> {
194
+ return this.request<any>('DELETE', `/v1/credentials/${id}`);
195
+ }
196
+
197
+ /**
198
+ * Emitir Factura Electrónica Homologada (CAE)
199
+ */
200
+ async emitInvoice(data: InvoiceInput, idempotencyKey?: string): Promise<InvoiceResponse> {
201
+ return this.request<InvoiceResponse>('POST', '/v1/invoices', data, idempotencyKey);
202
+ }
203
+
204
+ /**
205
+ * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
206
+ */
207
+ async getInvoicePdfBuffer(id: string): Promise<Buffer> {
208
+ const response = await fetch(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
209
+ method: 'GET',
210
+ headers: {
211
+ 'Authorization': `Bearer ${this.apiKey}`
212
+ }
213
+ });
214
+
215
+ if (!response.ok) {
216
+ throw new Error(`Failed to fetch PDF (${response.status})`);
217
+ }
218
+
219
+ const arrayBuffer = await response.arrayBuffer();
220
+ return Buffer.from(arrayBuffer);
221
+ }
222
+
223
+ /**
224
+ * Obtener Consumos y Estado del Plan (Billing)
225
+ */
226
+ async getBillingStatus(): Promise<BillingStatusResponse> {
227
+ return this.request<BillingStatusResponse>('GET', '/v1/billing/status');
228
+ }
229
+
230
+ /**
231
+ * Obtener Ajustes de Telegram por Tenant
232
+ */
233
+ async getTelegramSettings(): Promise<TelegramSettingsResponse> {
234
+ return this.request<TelegramSettingsResponse>('GET', '/v1/settings/telegram');
235
+ }
236
+
237
+ /**
238
+ * Guardar / Actualizar Ajustes de Telegram
239
+ */
240
+ async saveTelegramSettings(data: TelegramSettingsInput): Promise<any> {
241
+ return this.request<any>('POST', '/v1/settings/telegram', data);
242
+ }
243
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["es6", "dom"],
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src/**/*"]
15
+ }