keycae-ts 1.0.0 → 1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 KeyCAE Software S.A.
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 CHANGED
@@ -1,96 +1,183 @@
1
1
  # keycae-ts 🚀
2
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.
3
+ [![npm version](https://img.shields.io/npm/v/keycae-ts.svg)](https://www.npmjs.com/package/keycae-ts)
4
+ [![npm downloads](https://img.shields.io/npm/dm/keycae-ts.svg)](https://www.npmjs.com/package/keycae-ts)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
6
 
5
- ## Instalación
7
+ Cliente SDK oficial en **TypeScript** y **JavaScript** para interactuar con **KeyCAE.ar** y emitir facturación electrónica oficial ante **ARCA (ex AFIP)**.
6
8
 
7
- Instala el SDK en tu proyecto Node.js/TypeScript:
9
+ ## Instalación
8
10
 
9
11
  ```bash
10
12
  npm install keycae-ts
11
- # O usando yarn / pnpm
12
- yarn add keycae-ts
13
- pnpm add keycae-ts
14
13
  ```
15
14
 
16
- ## Inicio Rápido (Modelo A: Delegación Directa ⭐)
15
+ ## Inicio Rápido
16
+
17
+ El SDK soporta tanto el **Sandbox Público** (sin cuenta, ideal para desarrollo rápido) como el entorno de **Producción** (con cuenta registrada):
17
18
 
18
- Esta es la forma recomendada por defecto. En minutos podés facturar sin lidiar con llaves privadas o subir archivos de certificados.
19
+ * **Para Probar en Sandbox (Sin Cuenta):** Usa la clave pública `sk_test_public_sandbox_cuit_20999999999` y el CUIT de pruebas `20999999999`.
20
+ * **Para Producción (Con Cuenta):** Regístrate en [keycae.ar](https://keycae.ar) para obtener tu API Key `sk_live_...` y configura tu CUIT real.
19
21
 
20
22
  ```typescript
21
23
  import { KeyCaeClient } from 'keycae-ts';
22
24
 
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();
25
+ // Ejemplo para Sandbox Público:
26
+ const client = new KeyCaeClient('sk_test_public_sandbox_cuit_20999999999');
27
+ // O para producción: const client = new KeyCaeClient('sk_live_tu_api_key');
28
+
29
+ // Consultar contribuyente
30
+ const taxpayer = await client.getTaxpayer('20254459306');
31
+ console.log(`${taxpayer.nombre} | ${taxpayer.estado}`);
32
+
33
+ // Verificar qué tipos de factura puede emitir
34
+ const capability = await client.checkEmissionCapability('20254459306');
35
+ console.log(`Tipos compatibles: ${capability.compatible_types.join(', ')}`);
36
+ console.log(capability.recommendation);
37
+
38
+ // Emitir factura
39
+ const invoice = await client.emitInvoice({
40
+ cuit_emisor: '20254459306',
41
+ punto_de_venta: 1,
42
+ tipo_comprobante: 'B',
43
+ receptor: { tipo_doc: 'CUIT', nro_doc: '20333444555' },
44
+ conceptos: [{ descripcion: 'Servicios', precio: 15000 }]
45
+ }, 'idempotency_key_42');
46
+
47
+ console.log(`CAE: ${invoice.cae}`);
48
+ console.log(`PDF: ${invoice.url_pdf}`);
68
49
  ```
69
50
 
70
- ## Notificaciones en Tiempo Real (Telegram Alerts)
51
+ ## Modelos de Conexión
71
52
 
72
- Configurá tu bot de Telegram a través de la API para recibir alertas móviles al instante de cada comprobante emitido:
53
+ ### Modalidad A: Delegación Directa (Recomendada)
54
+ Sin certificados, sin llaves privadas. En minutos facturás.
73
55
 
74
56
  ```typescript
75
- import { KeyCaeClient } from 'keycae-ts';
57
+ const delegation = await client.createDelegation({
58
+ cuit: '20254459306',
59
+ organization: 'Tu Empresa'
60
+ });
61
+ ```
76
62
 
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();
63
+ ### Modalidad B: Bóvedas KMS
64
+ Generación segura de claves RSA y CSR.
65
+
66
+ ```typescript
67
+ const credential = await client.createCredential({
68
+ cuit: '20254459306',
69
+ organization: 'Tu Empresa'
70
+ });
92
71
  ```
93
72
 
73
+ ### Modalidad C: Importar Certificado
74
+ Subida directa de certificados (.crt) y llaves (.key).
75
+
76
+ ```typescript
77
+ await client.importCredential({
78
+ cuit: '20254459306',
79
+ organization: 'Tu Empresa',
80
+ certificate: certificatePem,
81
+ private_key: privateKeyPem
82
+ });
83
+ ```
84
+
85
+ ## Métodos Disponibles
86
+
87
+ ### Taxpayers
88
+ | Método | Descripción |
89
+ |--------|-------------|
90
+ | `getTaxpayer(cuit)` | Consultar contribuyente en padrón ARCA |
91
+ | `checkEmissionCapability(cuit)` | Verificar tipos de factura compatibles |
92
+
93
+ ### Delegations
94
+ | Método | Descripción |
95
+ |--------|-------------|
96
+ | `createDelegation(data)` | Iniciar delegación directa |
97
+ | `checkDelegationStatus()` | Consultar estado de delegación |
98
+
99
+ ### Credentials (KMS)
100
+ | Método | Descripción |
101
+ |--------|-------------|
102
+ | `createCredential(data)` | Generar RSA keypair + CSR |
103
+ | `listCredentials()` | Listar certificados registrados |
104
+ | `importCredential(data)` | Importar certificado existente |
105
+ | `activateCredential(id, cert)` | Activar bóveda con certificado ARCA |
106
+ | `deleteCredential(id)` | Eliminar bóveda de claves |
107
+
108
+ ### Invoices
109
+ | Método | Descripción |
110
+ |--------|-------------|
111
+ | `emitInvoice(data, idempotencyKey?)` | Emitir factura electrónica (CAE) |
112
+ | `getInvoice(id)` | Obtener detalles de factura |
113
+ | `listInvoices(limit?, offset?)` | Listar facturas recientes |
114
+ | `getInvoicePdfBuffer(id)` | Descargar PDF de factura |
115
+
116
+ ### Puntos de Venta
117
+ | Método | Descripción |
118
+ |--------|-------------|
119
+ | `listPuntosDeVenta()` | Listar puntos de venta habilitados |
120
+
121
+ ### Billing & Settings
122
+ | Método | Descripción |
123
+ |--------|-------------|
124
+ | `getBillingStatus()` | Estado del plan y consumo |
125
+ | `getTelegramSettings()` | Obtener configuración Telegram |
126
+ | `saveTelegramSettings(data)` | Guardar configuración Telegram |
127
+ | `health()` | Health check de la API |
128
+
129
+ ### Partners (ERPs / SaaS)
130
+ | Método | Descripción |
131
+ |--------|-------------|
132
+ | `createPartnerSubaccount(data)` | Crear subcuenta completa para un cliente final (usuario + API Key) |
133
+ | `listPartnerSubaccounts()` | Listar tus clientes con plan y consumo mensual |
134
+ | `preauthorizeCuit(cuit)` | Pre-autorizar un CUIT para facturación consolidada |
135
+ | `getPartnerConfig(partnerId)` | Configuración pública de co-branding (sin auth) |
136
+
137
+ > Los métodos de Partners requieren instanciar el cliente con tu **API Key de Partner** (`sk_partner_live_...`) y solo deben usarse desde tu backend:
138
+ >
139
+ > ```typescript
140
+ > const partnerClient = new KeyCaeClient('sk_partner_live_mi-erp_...');
141
+ >
142
+ > const sub = await partnerClient.createPartnerSubaccount({
143
+ > cuit: '20304567891',
144
+ > organization: 'Cliente S.A.',
145
+ > email: 'cliente@empresa.com'
146
+ > });
147
+ > // sub.api_key y sub.password se devuelven UNA sola vez
148
+ >
149
+ > const { clients, total } = await partnerClient.listPartnerSubaccounts();
150
+ > ```
151
+ >
152
+ > 📖 Guía completa del programa de partners: [keycae.ar/docs/partners.md](https://keycae.ar/docs/partners.md)
153
+
154
+ ## Tipos de Comprobante
155
+
156
+ | Tipo | Descripción |
157
+ |------|-------------|
158
+ | `A` | IVA discriminado (Responsable Inscripto → RI) |
159
+ | `B` | Consumidor Final (RI → CF) |
160
+ | `C` | Exento (Monotributo / Exento) |
161
+ | `M` | Monotributo |
162
+ | `E` | Exportación |
163
+ | `NCA` `NCB` `NCC` `NCE` `NCM` | Notas de Crédito (A, B, C, E, M) |
164
+ | `NDA` `NDB` `NDC` `NDE` `NDM` | Notas de Débito (A, B, C, E, M) |
165
+
166
+ ## Alertas Telegram
167
+
168
+ ```typescript
169
+ await client.saveTelegramSettings({
170
+ telegram_bot_token: '123456:***',
171
+ telegram_chat_id: '987654321'
172
+ });
173
+ ```
174
+
175
+ ## Documentación
176
+
177
+ - 📖 [docs.keycae.ar](https://docs.keycae.ar) — Documentación interactiva
178
+ - 📄 [llms.txt](https://keycae.ar/llms.txt) — Para AI agents
179
+ - 🔌 [MCP Server](https://www.npmjs.com/package/keycae-mcp) — Para Cursor/Claude
180
+
94
181
  ## Licencia
95
182
 
96
183
  MIT
package/dist/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export interface DomicilioFiscal {
2
+ direccion: string | null;
3
+ localidad: string | null;
4
+ cod_postal: string | null;
5
+ provincia: string | null;
6
+ }
1
7
  export interface TaxpayerResponse {
2
8
  cuit: string;
3
9
  nombre: string;
@@ -5,23 +11,63 @@ export interface TaxpayerResponse {
5
11
  categoria_monotributo?: string;
6
12
  es_iva_inscripto: boolean;
7
13
  estado: string;
14
+ condicion_iva?: string;
15
+ actividades?: string[];
16
+ domicilio_fiscal?: DomicilioFiscal;
8
17
  }
9
18
  export interface InvoiceReceptor {
10
- tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
19
+ tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE' | 'SIN_IDENTIFICAR';
11
20
  nro_doc: string;
21
+ razon_social?: string;
22
+ condicion_iva?: string;
12
23
  }
13
24
  export interface InvoiceItem {
14
25
  descripcion: string;
15
26
  precio: number;
27
+ cantidad?: number;
28
+ alicuota_iva?: number;
29
+ }
30
+ export interface Tributo {
31
+ id: number;
32
+ descripcion: string;
33
+ base_imponible: number;
34
+ alicuota: number;
35
+ importe: number;
36
+ }
37
+ export interface Opcional {
38
+ id: string;
39
+ valor: string;
40
+ }
41
+ export interface CondicionesIvaResponse {
42
+ condiciones: {
43
+ codigo: number;
44
+ nombre: string;
45
+ }[];
16
46
  }
17
47
  export interface InvoiceInput {
18
48
  cuit_emisor: string;
19
49
  punto_de_venta: number;
20
- tipo_comprobante: 'A' | 'B' | 'C' | 'M';
50
+ tipo_comprobante: 'A' | 'B' | 'C' | 'M' | 'E' | 'NCA' | 'NCB' | 'NCC' | 'NCE' | 'NCM' | 'NDA' | 'NDB' | 'NDC' | 'NDE' | 'NDM' | 'FCE_A' | 'FCE_B' | 'FCE_C' | 'FCE_NDA' | 'FCE_NDB' | 'FCE_NDC' | 'FCE_NCA' | 'FCE_NCB' | 'FCE_NCC';
21
51
  receptor: InvoiceReceptor;
22
52
  conceptos: InvoiceItem[];
53
+ tributos?: Tributo[];
54
+ moneda?: string;
55
+ moneda_cotizacion?: number;
56
+ fecha_comprobante?: string;
57
+ fecha_servicio_desde?: string;
58
+ fecha_servicio_hasta?: string;
59
+ fecha_vto_pago?: string;
60
+ condicion_iva_receptor?: number;
61
+ opcionales?: Opcional[];
23
62
  brand_logo_url?: string;
24
63
  brand_color?: string;
64
+ cbtes_asociados?: {
65
+ tipo: string | number;
66
+ punto_de_venta: number;
67
+ numero: number;
68
+ cuit?: string;
69
+ fecha?: string;
70
+ }[];
25
71
  }
26
72
  export interface InvoiceResponse {
27
73
  id: string;
@@ -61,7 +107,7 @@ export interface DelegationInput {
61
107
  }
62
108
  export interface DelegationResponse {
63
109
  id: string;
64
- status: 'pending' | 'accepted' | 'rejected';
110
+ status: 'pending' | 'accepted' | 'rejected' | 'pending_auto';
65
111
  cuit: string;
66
112
  organization: string;
67
113
  representativeCuit: string;
@@ -89,6 +135,70 @@ export interface KmsImportInput {
89
135
  certificate: string;
90
136
  private_key: string;
91
137
  }
138
+ export interface PuntoDeVenta {
139
+ numero: number;
140
+ tipoEmision: string;
141
+ tipoAutomatizacion?: string;
142
+ fechaServicioDesde?: string;
143
+ fechaServicioHasta?: string;
144
+ }
145
+ export interface EmissionCapability {
146
+ cuit: string;
147
+ condicion_iva: string;
148
+ compatible_types: string[];
149
+ recommendation: string;
150
+ tip: string;
151
+ }
152
+ export interface HealthResponse {
153
+ status: string;
154
+ version?: string;
155
+ uptime?: number;
156
+ }
157
+ export interface PartnerSubaccountInput {
158
+ /** CUIT fiscal del cliente final (11 dígitos, sin guiones) */
159
+ cuit: string;
160
+ /** Razón social del cliente final */
161
+ organization: string;
162
+ /** Email de acceso del cliente final */
163
+ email: string;
164
+ }
165
+ export interface PartnerSubaccountResponse {
166
+ id: string;
167
+ cuit: string;
168
+ organization: string;
169
+ email: string;
170
+ /** Contraseña generada — se devuelve UNA sola vez. Entregar por canal seguro. */
171
+ password: string;
172
+ /** API Key live de la subcuenta — se devuelve UNA sola vez. */
173
+ api_key: string;
174
+ partner_id: string;
175
+ }
176
+ export interface PartnerClient {
177
+ cuit: string;
178
+ organization: string;
179
+ email: string;
180
+ plan: 'free' | 'developer' | 'platform';
181
+ invoices_this_month: number;
182
+ created_at: string | null;
183
+ }
184
+ export interface PartnerClientsResponse {
185
+ partner_id: string;
186
+ total: number;
187
+ clients: PartnerClient[];
188
+ }
189
+ export interface PartnerPreauthResponse {
190
+ success: boolean;
191
+ message: string;
192
+ partner_id: string;
193
+ cuit: string;
194
+ }
195
+ export interface PartnerPublicConfig {
196
+ id: string;
197
+ name: string;
198
+ logo_url: string;
199
+ brand_color: string;
200
+ billing_mode: 'decentralized' | 'consolidated';
201
+ }
92
202
  export declare class KeyCaeClient {
93
203
  private apiKey;
94
204
  private baseUrl;
@@ -98,6 +208,10 @@ export declare class KeyCaeClient {
98
208
  * Consultar Contribuyente en Padrón ARCA
99
209
  */
100
210
  getTaxpayer(cuit: string): Promise<TaxpayerResponse>;
211
+ /**
212
+ * Verificar qué tipos de factura puede emitir un CUIT según su condición fiscal
213
+ */
214
+ checkEmissionCapability(cuit: string): Promise<EmissionCapability>;
101
215
  /**
102
216
  * Registrar / Iniciar Direct Delegation
103
217
  */
@@ -110,6 +224,10 @@ export declare class KeyCaeClient {
110
224
  * Crear Bóveda de Claves KMS & Generar CSR
111
225
  */
112
226
  createCredential(data: KmsCredentialInput): Promise<KmsCredentialResponse>;
227
+ /**
228
+ * Listar Credenciales Digitales Registradas
229
+ */
230
+ listCredentials(): Promise<KmsCredentialResponse[]>;
113
231
  /**
114
232
  * Importar Credenciales de Firma Existentes (.key y .crt)
115
233
  */
@@ -126,10 +244,27 @@ export declare class KeyCaeClient {
126
244
  * Emitir Factura Electrónica Homologada (CAE)
127
245
  */
128
246
  emitInvoice(data: InvoiceInput, idempotencyKey?: string): Promise<InvoiceResponse>;
247
+ /**
248
+ * Obtener Detalles de una Factura por ID
249
+ */
250
+ getInvoice(id: string): Promise<InvoiceResponse>;
251
+ /**
252
+ * Listar Facturas Recientes
253
+ */
254
+ listInvoices(limit?: number, offset?: number): Promise<{
255
+ invoices: InvoiceResponse[];
256
+ total: number;
257
+ }>;
129
258
  /**
130
259
  * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
131
260
  */
132
- getInvoicePdfBuffer(id: string): Promise<Buffer>;
261
+ getInvoicePdfBuffer(id: string, options?: {
262
+ format?: 'a4' | 'ticket';
263
+ }): Promise<Buffer>;
264
+ /**
265
+ * Listar Puntos de Venta Habilitados para Facturación Electrónica
266
+ */
267
+ listPuntosDeVenta(): Promise<PuntoDeVenta[]>;
133
268
  /**
134
269
  * Obtener Consumos y Estado del Plan (Billing)
135
270
  */
@@ -142,4 +277,38 @@ export declare class KeyCaeClient {
142
277
  * Guardar / Actualizar Ajustes de Telegram
143
278
  */
144
279
  saveTelegramSettings(data: TelegramSettingsInput): Promise<any>;
280
+ /**
281
+ * Health Check de la API
282
+ */
283
+ health(): Promise<HealthResponse>;
284
+ /**
285
+ * Obtener tabla de condiciones IVA del receptor (15 códigos oficiales ARCA)
286
+ */
287
+ getCondicionesIva(): Promise<CondicionesIvaResponse>;
288
+ /**
289
+ * Consultar cotización de una moneda extranjera vs peso (vía ARCA)
290
+ */
291
+ getCotizacionMoneda(moneda: string): Promise<{
292
+ moneda: string;
293
+ cotizacion: number;
294
+ }>;
295
+ /**
296
+ * Crear una subcuenta completa (usuario + perfil + API Key) para un
297
+ * cliente final de tu ERP. La password y api_key se devuelven una sola vez.
298
+ */
299
+ createPartnerSubaccount(data: PartnerSubaccountInput): Promise<PartnerSubaccountResponse>;
300
+ /**
301
+ * Listar los clientes vinculados a tu partner, con plan y consumo mensual.
302
+ */
303
+ listPartnerSubaccounts(): Promise<PartnerClientsResponse>;
304
+ /**
305
+ * Pre-autorizar el CUIT de un cliente para facturación consolidada
306
+ * (el cliente no pasará por la pasarela de pago al registrarse).
307
+ */
308
+ preauthorizeCuit(cuit: string): Promise<PartnerPreauthResponse>;
309
+ /**
310
+ * Consultar la configuración pública de co-branding de un partner
311
+ * (endpoint público — no requiere autenticación).
312
+ */
313
+ getPartnerConfig(partnerId: string): Promise<PartnerPublicConfig>;
145
314
  }
package/dist/index.js CHANGED
@@ -5,10 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.KeyCaeClient = void 0;
7
7
  const node_fetch_1 = __importDefault(require("node-fetch"));
8
+ // ════════════════════════════════════════════════════════════════════
9
+ // CLIENT
10
+ // ════════════════════════════════════════════════════════════════════
8
11
  class KeyCaeClient {
9
- constructor(apiKey, baseUrl = 'https://api.keycae.ar') {
12
+ constructor(apiKey, baseUrl = 'https://keycae.ar') {
10
13
  this.apiKey = apiKey;
11
- this.baseUrl = baseUrl;
14
+ this.baseUrl = baseUrl.replace(/\/$/, '');
12
15
  }
13
16
  async request(method, path, body, idempotencyKey) {
14
17
  const headers = {
@@ -24,21 +27,60 @@ class KeyCaeClient {
24
27
  body: body ? JSON.stringify(body) : undefined
25
28
  });
26
29
  if (!response.ok) {
27
- let errorDetails = '';
30
+ let errorData;
28
31
  try {
29
- errorDetails = await response.text();
32
+ errorData = await response.json();
30
33
  }
31
- catch (e) { }
32
- throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
34
+ catch {
35
+ const text = await response.text().catch(() => '');
36
+ throw new Error(`KeyCAE API Error (${response.status}): ${text || response.statusText}`);
37
+ }
38
+ const message = errorData?.error?.message || JSON.stringify(errorData);
39
+ const hint = errorData?.error?.ai_action_hint || '';
40
+ throw new Error(`KeyCAE API Error (${response.status}): ${message}${hint ? ` [hint: ${hint}]` : ''}`);
33
41
  }
34
42
  return response.json();
35
43
  }
44
+ // ── Taxpayers ─────────────────────────────────────────────────────
36
45
  /**
37
46
  * Consultar Contribuyente en Padrón ARCA
38
47
  */
39
48
  async getTaxpayer(cuit) {
40
49
  return this.request('GET', `/v1/taxpayers/${cuit}`);
41
50
  }
51
+ /**
52
+ * Verificar qué tipos de factura puede emitir un CUIT según su condición fiscal
53
+ */
54
+ async checkEmissionCapability(cuit) {
55
+ const taxpayer = await this.getTaxpayer(cuit);
56
+ const condition = taxpayer.condicion_iva || taxpayer.estado || '';
57
+ let compatibleTypes = [];
58
+ let recommendation = '';
59
+ if (condition.toLowerCase().includes('monotributo')) {
60
+ compatibleTypes = ['C', 'M'];
61
+ recommendation = 'Como Monotributista, podés emitir Factura C (exenta) o Factura M (monotributo). NO podés emitir Factura A o B.';
62
+ }
63
+ else if (condition.toLowerCase().includes('responsable inscripto') || condition.toLowerCase().includes('ri')) {
64
+ compatibleTypes = ['A', 'B'];
65
+ recommendation = 'Como Responsable Inscripto, podés emitir Factura A (IVA discriminado) o Factura B (consumidor final).';
66
+ }
67
+ else if (condition.toLowerCase().includes('exento')) {
68
+ compatibleTypes = ['C'];
69
+ recommendation = 'Como Exento, solo podés emitir Factura C (exenta).';
70
+ }
71
+ else {
72
+ compatibleTypes = ['C'];
73
+ recommendation = 'No se pudo determinar la condición impositiva. Se recomienda Factura C por defecto.';
74
+ }
75
+ return {
76
+ cuit,
77
+ condicion_iva: condition,
78
+ compatible_types: compatibleTypes,
79
+ recommendation,
80
+ tip: 'Usá estos tipos al emitir facturas con emitInvoice para evitar errores de ARCA.'
81
+ };
82
+ }
83
+ // ── Delegations ───────────────────────────────────────────────────
42
84
  /**
43
85
  * Registrar / Iniciar Direct Delegation
44
86
  */
@@ -51,12 +93,19 @@ class KeyCaeClient {
51
93
  async checkDelegationStatus() {
52
94
  return this.request('GET', '/v1/delegations/status');
53
95
  }
96
+ // ── Credentials (KMS) ────────────────────────────────────────────
54
97
  /**
55
98
  * Crear Bóveda de Claves KMS & Generar CSR
56
99
  */
57
100
  async createCredential(data) {
58
101
  return this.request('POST', '/v1/credentials', data);
59
102
  }
103
+ /**
104
+ * Listar Credenciales Digitales Registradas
105
+ */
106
+ async listCredentials() {
107
+ return this.request('GET', '/v1/credentials');
108
+ }
60
109
  /**
61
110
  * Importar Credenciales de Firma Existentes (.key y .crt)
62
111
  */
@@ -75,17 +124,35 @@ class KeyCaeClient {
75
124
  async deleteCredential(id) {
76
125
  return this.request('DELETE', `/v1/credentials/${id}`);
77
126
  }
127
+ // ── Invoices ──────────────────────────────────────────────────────
78
128
  /**
79
129
  * Emitir Factura Electrónica Homologada (CAE)
80
130
  */
81
131
  async emitInvoice(data, idempotencyKey) {
82
132
  return this.request('POST', '/v1/invoices', data, idempotencyKey);
83
133
  }
134
+ /**
135
+ * Obtener Detalles de una Factura por ID
136
+ */
137
+ async getInvoice(id) {
138
+ return this.request('GET', `/v1/invoices/${id}`);
139
+ }
140
+ /**
141
+ * Listar Facturas Recientes
142
+ */
143
+ async listInvoices(limit = 10, offset = 0) {
144
+ const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
145
+ return this.request('GET', `/v1/invoices?${params}`);
146
+ }
84
147
  /**
85
148
  * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
86
149
  */
87
- async getInvoicePdfBuffer(id) {
88
- const response = await (0, node_fetch_1.default)(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
150
+ async getInvoicePdfBuffer(id, options) {
151
+ const url = new URL(`${this.baseUrl}/v1/invoices/${id}/pdf`);
152
+ if (options?.format) {
153
+ url.searchParams.append('format', options.format);
154
+ }
155
+ const response = await (0, node_fetch_1.default)(url.toString(), {
89
156
  method: 'GET',
90
157
  headers: {
91
158
  'Authorization': `Bearer ${this.apiKey}`
@@ -94,15 +161,23 @@ class KeyCaeClient {
94
161
  if (!response.ok) {
95
162
  throw new Error(`Failed to fetch PDF (${response.status})`);
96
163
  }
97
- const arrayBuffer = await response.arrayBuffer();
98
- return Buffer.from(arrayBuffer);
164
+ return Buffer.from(await response.arrayBuffer());
165
+ }
166
+ // ── Puntos de Venta ───────────────────────────────────────────────
167
+ /**
168
+ * Listar Puntos de Venta Habilitados para Facturación Electrónica
169
+ */
170
+ async listPuntosDeVenta() {
171
+ return this.request('GET', '/v1/pos');
99
172
  }
173
+ // ── Billing ───────────────────────────────────────────────────────
100
174
  /**
101
175
  * Obtener Consumos y Estado del Plan (Billing)
102
176
  */
103
177
  async getBillingStatus() {
104
178
  return this.request('GET', '/v1/billing/status');
105
179
  }
180
+ // ── Telegram Settings ─────────────────────────────────────────────
106
181
  /**
107
182
  * Obtener Ajustes de Telegram por Tenant
108
183
  */
@@ -115,5 +190,56 @@ class KeyCaeClient {
115
190
  async saveTelegramSettings(data) {
116
191
  return this.request('POST', '/v1/settings/telegram', data);
117
192
  }
193
+ // ── Health ────────────────────────────────────────────────────────
194
+ /**
195
+ * Health Check de la API
196
+ */
197
+ async health() {
198
+ return this.request('GET', '/health');
199
+ }
200
+ // ── Condición IVA Receptor ──────────────────────────────────────
201
+ /**
202
+ * Obtener tabla de condiciones IVA del receptor (15 códigos oficiales ARCA)
203
+ */
204
+ async getCondicionesIva() {
205
+ return this.request('GET', '/v1/taxpayers/condiciones-iva');
206
+ }
207
+ // ── Cotización de Moneda ────────────────────────────────────────
208
+ /**
209
+ * Consultar cotización de una moneda extranjera vs peso (vía ARCA)
210
+ */
211
+ async getCotizacionMoneda(moneda) {
212
+ return this.request('GET', `/v1/cotizacion/${moneda}`);
213
+ }
214
+ // ── Partners (ERP / SaaS) ────────────────────────────────────────
215
+ // Estos métodos requieren instanciar el cliente con tu API Key de
216
+ // Partner (sk_partner_live_...) — solo desde tu backend.
217
+ /**
218
+ * Crear una subcuenta completa (usuario + perfil + API Key) para un
219
+ * cliente final de tu ERP. La password y api_key se devuelven una sola vez.
220
+ */
221
+ async createPartnerSubaccount(data) {
222
+ return this.request('POST', '/v1/partners/subaccounts', data);
223
+ }
224
+ /**
225
+ * Listar los clientes vinculados a tu partner, con plan y consumo mensual.
226
+ */
227
+ async listPartnerSubaccounts() {
228
+ return this.request('GET', '/v1/partners/subaccounts');
229
+ }
230
+ /**
231
+ * Pre-autorizar el CUIT de un cliente para facturación consolidada
232
+ * (el cliente no pasará por la pasarela de pago al registrarse).
233
+ */
234
+ async preauthorizeCuit(cuit) {
235
+ return this.request('POST', '/v1/partners/preauthorize', { cuit });
236
+ }
237
+ /**
238
+ * Consultar la configuración pública de co-branding de un partner
239
+ * (endpoint público — no requiere autenticación).
240
+ */
241
+ async getPartnerConfig(partnerId) {
242
+ return this.request('GET', `/v1/partners/${encodeURIComponent(partnerId)}/config`);
243
+ }
118
244
  }
119
245
  exports.KeyCaeClient = KeyCaeClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycae-ts",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Official TypeScript & JavaScript SDK client for KeyCAE.ar impositive compliance API (ARCA)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,6 +20,11 @@
20
20
  ],
21
21
  "author": "KeyCAE Community",
22
22
  "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/AMKRS3/keycae-packages",
26
+ "directory": "keycae-ts"
27
+ },
23
28
  "dependencies": {
24
29
  "node-fetch": "^2.6.9"
25
30
  },
package/src/index.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  import fetch from 'node-fetch';
2
2
 
3
+ // ════════════════════════════════════════════════════════════════════
4
+ // INTERFACES
5
+ // ════════════════════════════════════════════════════════════════════
6
+
7
+ export interface DomicilioFiscal {
8
+ direccion: string | null;
9
+ localidad: string | null;
10
+ cod_postal: string | null;
11
+ provincia: string | null;
12
+ }
13
+
3
14
  export interface TaxpayerResponse {
4
15
  cuit: string;
5
16
  nombre: string;
@@ -7,26 +18,71 @@ export interface TaxpayerResponse {
7
18
  categoria_monotributo?: string;
8
19
  es_iva_inscripto: boolean;
9
20
  estado: string;
21
+ condicion_iva?: string;
22
+ actividades?: string[];
23
+ domicilio_fiscal?: DomicilioFiscal;
10
24
  }
11
25
 
12
26
  export interface InvoiceReceptor {
13
- tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
27
+ tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE' | 'SIN_IDENTIFICAR';
14
28
  nro_doc: string;
29
+ razon_social?: string;
30
+ condicion_iva?: string;
15
31
  }
16
32
 
17
33
  export interface InvoiceItem {
18
34
  descripcion: string;
19
35
  precio: number;
36
+ cantidad?: number;
37
+ alicuota_iva?: number;
38
+ }
39
+
40
+ export interface Tributo {
41
+ id: number;
42
+ descripcion: string;
43
+ base_imponible: number;
44
+ alicuota: number;
45
+ importe: number;
46
+ }
47
+
48
+ export interface Opcional {
49
+ id: string;
50
+ valor: string;
51
+ }
52
+
53
+ export interface CondicionesIvaResponse {
54
+ condiciones: { codigo: number; nombre: string }[];
20
55
  }
21
56
 
22
57
  export interface InvoiceInput {
23
58
  cuit_emisor: string;
24
59
  punto_de_venta: number;
25
- tipo_comprobante: 'A' | 'B' | 'C' | 'M';
60
+ tipo_comprobante: 'A' | 'B' | 'C' | 'M' | 'E'
61
+ | 'NCA' | 'NCB' | 'NCC' | 'NCE' | 'NCM'
62
+ | 'NDA' | 'NDB' | 'NDC' | 'NDE' | 'NDM'
63
+ | 'FCE_A' | 'FCE_B' | 'FCE_C'
64
+ | 'FCE_NDA' | 'FCE_NDB' | 'FCE_NDC'
65
+ | 'FCE_NCA' | 'FCE_NCB' | 'FCE_NCC';
26
66
  receptor: InvoiceReceptor;
27
67
  conceptos: InvoiceItem[];
68
+ tributos?: Tributo[];
69
+ moneda?: string;
70
+ moneda_cotizacion?: number;
71
+ fecha_comprobante?: string;
72
+ fecha_servicio_desde?: string;
73
+ fecha_servicio_hasta?: string;
74
+ fecha_vto_pago?: string;
75
+ condicion_iva_receptor?: number;
76
+ opcionales?: Opcional[];
28
77
  brand_logo_url?: string;
29
78
  brand_color?: string;
79
+ cbtes_asociados?: {
80
+ tipo: string | number;
81
+ punto_de_venta: number;
82
+ numero: number;
83
+ cuit?: string;
84
+ fecha?: string;
85
+ }[];
30
86
  }
31
87
 
32
88
  export interface InvoiceResponse {
@@ -72,7 +128,7 @@ export interface DelegationInput {
72
128
 
73
129
  export interface DelegationResponse {
74
130
  id: string;
75
- status: 'pending' | 'accepted' | 'rejected';
131
+ status: 'pending' | 'accepted' | 'rejected' | 'pending_auto';
76
132
  cuit: string;
77
133
  organization: string;
78
134
  representativeCuit: string;
@@ -104,13 +160,92 @@ export interface KmsImportInput {
104
160
  private_key: string;
105
161
  }
106
162
 
163
+ export interface PuntoDeVenta {
164
+ numero: number;
165
+ tipoEmision: string;
166
+ tipoAutomatizacion?: string;
167
+ fechaServicioDesde?: string;
168
+ fechaServicioHasta?: string;
169
+ }
170
+
171
+ export interface EmissionCapability {
172
+ cuit: string;
173
+ condicion_iva: string;
174
+ compatible_types: string[];
175
+ recommendation: string;
176
+ tip: string;
177
+ }
178
+
179
+ export interface HealthResponse {
180
+ status: string;
181
+ version?: string;
182
+ uptime?: number;
183
+ }
184
+
185
+ // ── Partners (ERP / SaaS Integrations) ──────────────────────────────
186
+
187
+ export interface PartnerSubaccountInput {
188
+ /** CUIT fiscal del cliente final (11 dígitos, sin guiones) */
189
+ cuit: string;
190
+ /** Razón social del cliente final */
191
+ organization: string;
192
+ /** Email de acceso del cliente final */
193
+ email: string;
194
+ }
195
+
196
+ export interface PartnerSubaccountResponse {
197
+ id: string;
198
+ cuit: string;
199
+ organization: string;
200
+ email: string;
201
+ /** Contraseña generada — se devuelve UNA sola vez. Entregar por canal seguro. */
202
+ password: string;
203
+ /** API Key live de la subcuenta — se devuelve UNA sola vez. */
204
+ api_key: string;
205
+ partner_id: string;
206
+ }
207
+
208
+ export interface PartnerClient {
209
+ cuit: string;
210
+ organization: string;
211
+ email: string;
212
+ plan: 'free' | 'developer' | 'platform';
213
+ invoices_this_month: number;
214
+ created_at: string | null;
215
+ }
216
+
217
+ export interface PartnerClientsResponse {
218
+ partner_id: string;
219
+ total: number;
220
+ clients: PartnerClient[];
221
+ }
222
+
223
+ export interface PartnerPreauthResponse {
224
+ success: boolean;
225
+ message: string;
226
+ partner_id: string;
227
+ cuit: string;
228
+ }
229
+
230
+ export interface PartnerPublicConfig {
231
+ id: string;
232
+ name: string;
233
+ logo_url: string;
234
+ brand_color: string;
235
+ billing_mode: 'decentralized' | 'consolidated';
236
+ }
237
+
238
+ // ════════════════════════════════════════════════════════════════════
239
+ // CLIENT
240
+ // ════════════════════════════════════════════════════════════════════
241
+
107
242
  export class KeyCaeClient {
108
243
  private apiKey: string;
109
244
  private baseUrl: string;
110
245
 
111
- constructor(apiKey: string, baseUrl: string = 'https://api.keycae.ar') {
246
+ constructor(apiKey: string, baseUrl: string = 'https://keycae.ar') {
112
247
  this.apiKey = apiKey;
113
- this.baseUrl = baseUrl;
248
+ this.baseUrl = baseUrl.replace(/\/$/, '');
114
249
  }
115
250
 
116
251
  private async request<T>(
@@ -135,16 +270,23 @@ export class KeyCaeClient {
135
270
  });
136
271
 
137
272
  if (!response.ok) {
138
- let errorDetails = '';
273
+ let errorData: any;
139
274
  try {
140
- errorDetails = await response.text();
141
- } catch (e) {}
142
- throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
275
+ errorData = await response.json();
276
+ } catch {
277
+ const text = await response.text().catch(() => '');
278
+ throw new Error(`KeyCAE API Error (${response.status}): ${text || response.statusText}`);
279
+ }
280
+ const message = errorData?.error?.message || JSON.stringify(errorData);
281
+ const hint = errorData?.error?.ai_action_hint || '';
282
+ throw new Error(`KeyCAE API Error (${response.status}): ${message}${hint ? ` [hint: ${hint}]` : ''}`);
143
283
  }
144
284
 
145
285
  return response.json() as Promise<T>;
146
286
  }
147
287
 
288
+ // ── Taxpayers ─────────────────────────────────────────────────────
289
+
148
290
  /**
149
291
  * Consultar Contribuyente en Padrón ARCA
150
292
  */
@@ -152,6 +294,40 @@ export class KeyCaeClient {
152
294
  return this.request<TaxpayerResponse>('GET', `/v1/taxpayers/${cuit}`);
153
295
  }
154
296
 
297
+ /**
298
+ * Verificar qué tipos de factura puede emitir un CUIT según su condición fiscal
299
+ */
300
+ async checkEmissionCapability(cuit: string): Promise<EmissionCapability> {
301
+ const taxpayer = await this.getTaxpayer(cuit);
302
+ const condition = taxpayer.condicion_iva || taxpayer.estado || '';
303
+ let compatibleTypes: string[] = [];
304
+ let recommendation = '';
305
+
306
+ if (condition.toLowerCase().includes('monotributo')) {
307
+ compatibleTypes = ['C', 'M'];
308
+ recommendation = 'Como Monotributista, podés emitir Factura C (exenta) o Factura M (monotributo). NO podés emitir Factura A o B.';
309
+ } else if (condition.toLowerCase().includes('responsable inscripto') || condition.toLowerCase().includes('ri')) {
310
+ compatibleTypes = ['A', 'B'];
311
+ recommendation = 'Como Responsable Inscripto, podés emitir Factura A (IVA discriminado) o Factura B (consumidor final).';
312
+ } else if (condition.toLowerCase().includes('exento')) {
313
+ compatibleTypes = ['C'];
314
+ recommendation = 'Como Exento, solo podés emitir Factura C (exenta).';
315
+ } else {
316
+ compatibleTypes = ['C'];
317
+ recommendation = 'No se pudo determinar la condición impositiva. Se recomienda Factura C por defecto.';
318
+ }
319
+
320
+ return {
321
+ cuit,
322
+ condicion_iva: condition,
323
+ compatible_types: compatibleTypes,
324
+ recommendation,
325
+ tip: 'Usá estos tipos al emitir facturas con emitInvoice para evitar errores de ARCA.'
326
+ };
327
+ }
328
+
329
+ // ── Delegations ───────────────────────────────────────────────────
330
+
155
331
  /**
156
332
  * Registrar / Iniciar Direct Delegation
157
333
  */
@@ -166,6 +342,8 @@ export class KeyCaeClient {
166
342
  return this.request<DelegationResponse>('GET', '/v1/delegations/status');
167
343
  }
168
344
 
345
+ // ── Credentials (KMS) ────────────────────────────────────────────
346
+
169
347
  /**
170
348
  * Crear Bóveda de Claves KMS & Generar CSR
171
349
  */
@@ -173,6 +351,13 @@ export class KeyCaeClient {
173
351
  return this.request<KmsCredentialResponse>('POST', '/v1/credentials', data);
174
352
  }
175
353
 
354
+ /**
355
+ * Listar Credenciales Digitales Registradas
356
+ */
357
+ async listCredentials(): Promise<KmsCredentialResponse[]> {
358
+ return this.request<KmsCredentialResponse[]>('GET', '/v1/credentials');
359
+ }
360
+
176
361
  /**
177
362
  * Importar Credenciales de Firma Existentes (.key y .crt)
178
363
  */
@@ -194,6 +379,8 @@ export class KeyCaeClient {
194
379
  return this.request<any>('DELETE', `/v1/credentials/${id}`);
195
380
  }
196
381
 
382
+ // ── Invoices ──────────────────────────────────────────────────────
383
+
197
384
  /**
198
385
  * Emitir Factura Electrónica Homologada (CAE)
199
386
  */
@@ -201,11 +388,30 @@ export class KeyCaeClient {
201
388
  return this.request<InvoiceResponse>('POST', '/v1/invoices', data, idempotencyKey);
202
389
  }
203
390
 
391
+ /**
392
+ * Obtener Detalles de una Factura por ID
393
+ */
394
+ async getInvoice(id: string): Promise<InvoiceResponse> {
395
+ return this.request<InvoiceResponse>('GET', `/v1/invoices/${id}`);
396
+ }
397
+
398
+ /**
399
+ * Listar Facturas Recientes
400
+ */
401
+ async listInvoices(limit: number = 10, offset: number = 0): Promise<{ invoices: InvoiceResponse[]; total: number }> {
402
+ const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
403
+ return this.request<any>('GET', `/v1/invoices?${params}`);
404
+ }
405
+
204
406
  /**
205
407
  * Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
206
408
  */
207
- async getInvoicePdfBuffer(id: string): Promise<Buffer> {
208
- const response = await fetch(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
409
+ async getInvoicePdfBuffer(id: string, options?: { format?: 'a4' | 'ticket' }): Promise<Buffer> {
410
+ const url = new URL(`${this.baseUrl}/v1/invoices/${id}/pdf`);
411
+ if (options?.format) {
412
+ url.searchParams.append('format', options.format);
413
+ }
414
+ const response = await fetch(url.toString(), {
209
415
  method: 'GET',
210
416
  headers: {
211
417
  'Authorization': `Bearer ${this.apiKey}`
@@ -216,10 +422,20 @@ export class KeyCaeClient {
216
422
  throw new Error(`Failed to fetch PDF (${response.status})`);
217
423
  }
218
424
 
219
- const arrayBuffer = await response.arrayBuffer();
220
- return Buffer.from(arrayBuffer);
425
+ return Buffer.from(await response.arrayBuffer());
221
426
  }
222
427
 
428
+ // ── Puntos de Venta ───────────────────────────────────────────────
429
+
430
+ /**
431
+ * Listar Puntos de Venta Habilitados para Facturación Electrónica
432
+ */
433
+ async listPuntosDeVenta(): Promise<PuntoDeVenta[]> {
434
+ return this.request<PuntoDeVenta[]>('GET', '/v1/pos');
435
+ }
436
+
437
+ // ── Billing ───────────────────────────────────────────────────────
438
+
223
439
  /**
224
440
  * Obtener Consumos y Estado del Plan (Billing)
225
441
  */
@@ -227,6 +443,8 @@ export class KeyCaeClient {
227
443
  return this.request<BillingStatusResponse>('GET', '/v1/billing/status');
228
444
  }
229
445
 
446
+ // ── Telegram Settings ─────────────────────────────────────────────
447
+
230
448
  /**
231
449
  * Obtener Ajustes de Telegram por Tenant
232
450
  */
@@ -240,4 +458,66 @@ export class KeyCaeClient {
240
458
  async saveTelegramSettings(data: TelegramSettingsInput): Promise<any> {
241
459
  return this.request<any>('POST', '/v1/settings/telegram', data);
242
460
  }
461
+
462
+ // ── Health ────────────────────────────────────────────────────────
463
+
464
+ /**
465
+ * Health Check de la API
466
+ */
467
+ async health(): Promise<HealthResponse> {
468
+ return this.request<HealthResponse>('GET', '/health');
469
+ }
470
+
471
+ // ── Condición IVA Receptor ──────────────────────────────────────
472
+
473
+ /**
474
+ * Obtener tabla de condiciones IVA del receptor (15 códigos oficiales ARCA)
475
+ */
476
+ async getCondicionesIva(): Promise<CondicionesIvaResponse> {
477
+ return this.request<CondicionesIvaResponse>('GET', '/v1/taxpayers/condiciones-iva');
478
+ }
479
+
480
+ // ── Cotización de Moneda ────────────────────────────────────────
481
+
482
+ /**
483
+ * Consultar cotización de una moneda extranjera vs peso (vía ARCA)
484
+ */
485
+ async getCotizacionMoneda(moneda: string): Promise<{ moneda: string; cotizacion: number }> {
486
+ return this.request<any>('GET', `/v1/cotizacion/${moneda}`);
487
+ }
488
+
489
+ // ── Partners (ERP / SaaS) ────────────────────────────────────────
490
+ // Estos métodos requieren instanciar el cliente con tu API Key de
491
+ // Partner (sk_partner_live_...) — solo desde tu backend.
492
+
493
+ /**
494
+ * Crear una subcuenta completa (usuario + perfil + API Key) para un
495
+ * cliente final de tu ERP. La password y api_key se devuelven una sola vez.
496
+ */
497
+ async createPartnerSubaccount(data: PartnerSubaccountInput): Promise<PartnerSubaccountResponse> {
498
+ return this.request<PartnerSubaccountResponse>('POST', '/v1/partners/subaccounts', data);
499
+ }
500
+
501
+ /**
502
+ * Listar los clientes vinculados a tu partner, con plan y consumo mensual.
503
+ */
504
+ async listPartnerSubaccounts(): Promise<PartnerClientsResponse> {
505
+ return this.request<PartnerClientsResponse>('GET', '/v1/partners/subaccounts');
506
+ }
507
+
508
+ /**
509
+ * Pre-autorizar el CUIT de un cliente para facturación consolidada
510
+ * (el cliente no pasará por la pasarela de pago al registrarse).
511
+ */
512
+ async preauthorizeCuit(cuit: string): Promise<PartnerPreauthResponse> {
513
+ return this.request<PartnerPreauthResponse>('POST', '/v1/partners/preauthorize', { cuit });
514
+ }
515
+
516
+ /**
517
+ * Consultar la configuración pública de co-branding de un partner
518
+ * (endpoint público — no requiere autenticación).
519
+ */
520
+ async getPartnerConfig(partnerId: string): Promise<PartnerPublicConfig> {
521
+ return this.request<PartnerPublicConfig>('GET', `/v1/partners/${encodeURIComponent(partnerId)}/config`);
522
+ }
243
523
  }