@pimia/sdk 0.20.0 → 0.27.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/dist/api.d.ts CHANGED
@@ -301,6 +301,195 @@ export interface paths {
301
301
  patch?: never;
302
302
  trace?: never;
303
303
  };
304
+ "/apps": {
305
+ parameters: {
306
+ query?: never;
307
+ header?: never;
308
+ path?: never;
309
+ cookie?: never;
310
+ };
311
+ /**
312
+ * El catálogo de integraciones con el estado de cada una EN ESTA EMPRESA
313
+ * @description **Reservada al panel de Pimia.** Exige `apps:read`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
314
+ *
315
+ * `status` distingue tres cosas y no dos: `not_installed` (no hay fila),
316
+ * `installed` y `disabled` (la hubo y se apagó, con su config a salvo).
317
+ *
318
+ * `authorization` dice si el grant que sostiene la instalación sigue vivo.
319
+ * Hasta #699 nadie lo enlaza, así que hoy es `null` en todas; la forma está
320
+ * para que la pantalla no cambie cuando deje de serlo.
321
+ *
322
+ * ⚠️ `price_cents` va en subunidades y SIN formatear: formatearlo aquí
323
+ * clavaría el euro en un quinto sitio (#517), y el precio de una app es
324
+ * suyo. Quien lo pinte ya sabe en qué moneda cobra.
325
+ */
326
+ get: operations["apps.index"];
327
+ put?: never;
328
+ post?: never;
329
+ delete?: never;
330
+ options?: never;
331
+ head?: never;
332
+ patch?: never;
333
+ trace?: never;
334
+ };
335
+ "/apps/{slug}": {
336
+ parameters: {
337
+ query?: never;
338
+ header?: never;
339
+ path?: never;
340
+ cookie?: never;
341
+ };
342
+ /**
343
+ * La ficha de una integración: manifiesto, estado y su configuración
344
+ * ENMASCARADA (un secreto sale como si existe y sus últimos cuatro, nunca
345
+ * entero — ver {@see AppRegistry})
346
+ * @description **Reservada al panel de Pimia.** Exige `apps:read`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
347
+ */
348
+ get: operations["apps.show"];
349
+ put?: never;
350
+ post?: never;
351
+ delete?: never;
352
+ options?: never;
353
+ head?: never;
354
+ patch?: never;
355
+ trace?: never;
356
+ };
357
+ "/apps/{slug}/install": {
358
+ parameters: {
359
+ query?: never;
360
+ header?: never;
361
+ path?: never;
362
+ cookie?: never;
363
+ };
364
+ get?: never;
365
+ put?: never;
366
+ /**
367
+ * Instalar la integración en esta empresa: la ceremonia completa
368
+ * @description **Reservada al panel de Pimia.** Exige `apps:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
369
+ *
370
+ * Enlaza el grant OAuth de quien instala —el patrón Slack: la app se
371
+ * instala con el token de quien la instaló, y si esa persona se va, la
372
+ * empresa reinstala— y registra los endpoints de webhook que declara el
373
+ * manifiesto, con el `client_id` de la app y esta company. La app puede
374
+ * devolver en su callback la URL de entrega (`webhook_url`), que manda
375
+ * sobre la del manifiesto.
376
+ *
377
+ * `webhook_secret` viene SOLO cuando se acaba de crear el endpoint: es lo
378
+ * que la app necesita para verificar la firma HMAC, y no se vuelve a
379
+ * enseñar (ni se rota en un reintento, que dejaría a la app verificando con
380
+ * uno viejo).
381
+ *
382
+ * Idempotente: si ya estaba instalada responde 200 sin reescribir
383
+ * `installed_at` —el día que #702 cobre, volver a pulsar no puede volver a
384
+ * cobrar— pero sí reintenta los enganches que falten. Si estaba apagada, la
385
+ * reenciende conservando su config.
386
+ *
387
+ * ⚠️ Desde el #710 puede responder **409 `app_retired`**: el superadmin
388
+ * retiró la app del catálogo. No es un 404 —la integración existe y quien la
389
+ * tenga puesta la sigue viendo y la puede desinstalar—; lo que ya no se
390
+ * puede es darla de alta. Quien lo pinte tiene que clasificar por el `error`
391
+ * del cuerpo, no por el status.
392
+ */
393
+ post: operations["apps.install"];
394
+ /**
395
+ * Desinstalar: un botón, tres efectos
396
+ * @description **Reservada al panel de Pimia.** Exige `apps:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
397
+ *
398
+ * Revoca el grant que la sostenía (cascada de `TokenLifecycle`: sella el
399
+ * grant y sus refresh, borra los PAT de ese client en el esquema del
400
+ * tenant y emite `app.revoked` una sola vez), borra los endpoints de
401
+ * webhook de esta app en esta company, y apaga la fila.
402
+ *
403
+ * ⚠️ `billing.released` solo es `true` cuando de verdad había una partida
404
+ * que retirar, y **solo entonces `paid_until` significa algo** (#715). Si la
405
+ * app se cobra hoy pero esta suscripción nunca tuvo su partida —la
406
+ * instalación es anterior al precio, o la suscripción ya estaba cancelada—
407
+ * viene `nothing_to_release`. Quien pinte la frase no puede afirmar un mes
408
+ * pagado sin mirar cuál de las dos es.
409
+ *
410
+ * ⛔ Y hay un tercer «no se dio de baja» que **no se puede callar**:
411
+ * `release_failed`. Ahí la partida existía y Stripe no dejó quitarla, así
412
+ * que la integración queda desinstalada y **la suscripción la sigue
413
+ * cobrando** hasta que el reconciliador la cace. Callarlo es peor que
414
+ * equivocarse de frase: la empresa creería que dejó de pagar algo que se le
415
+ * sigue cobrando.
416
+ *
417
+ * La fila no se borra: «desinstalada» es un estado consultable, no la
418
+ * ausencia de información, y volver a instalar sale barato. La config se
419
+ * CONSERVA salvo que el manifiesto declare lo contrario, y la respuesta lo
420
+ * dice en `config_kept` — desinstalar por error no debe perder lo
421
+ * configurado.
422
+ */
423
+ delete: operations["apps.uninstall"];
424
+ options?: never;
425
+ head?: never;
426
+ patch?: never;
427
+ trace?: never;
428
+ };
429
+ "/apps/{slug}/config": {
430
+ parameters: {
431
+ query?: never;
432
+ header?: never;
433
+ path?: never;
434
+ cookie?: never;
435
+ };
436
+ /**
437
+ * La configuración de la integración, enmascarada
438
+ * @description **Reservada al panel de Pimia.** Exige `apps:read`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
439
+ */
440
+ get: operations["apps.config"];
441
+ /**
442
+ * Guardar configuración, validada contra el `config_schema` del manifiesto
443
+ * @description **Reservada al panel de Pimia.** Exige `apps:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
444
+ *
445
+ * Es un MERGE: lo que no viene, no se toca. Tiene que serlo porque quien
446
+ * edita desde una pantalla no tiene los secretos —solo ha visto sus últimos
447
+ * cuatro—, y un reemplazo los borraría cada vez que se cambia una URL. Para
448
+ * quitar un campo se manda `null`.
449
+ *
450
+ * Y se comprueba el resultado, no la entrada: si TRAS el merge faltara
451
+ * algún campo obligatorio, se rechaza con 422. Así la config no queda a
452
+ * medias sin que nadie lo note, y guardar solo un campo sigue valiendo.
453
+ */
454
+ put: operations["apps.updateConfig"];
455
+ post?: never;
456
+ delete?: never;
457
+ options?: never;
458
+ head?: never;
459
+ patch?: never;
460
+ trace?: never;
461
+ };
462
+ "/apps/{slug}/credential": {
463
+ parameters: {
464
+ query?: never;
465
+ header?: never;
466
+ path?: never;
467
+ cookie?: never;
468
+ };
469
+ get?: never;
470
+ put?: never;
471
+ /**
472
+ * Acuñar o ROTAR la credencial de entrada de la app en esta empresa
473
+ * @description **Reservada al panel de Pimia.** Exige `apps:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
474
+ *
475
+ * Devuelve el secreto EN CLARO, y es la única vez que sale: en la base solo
476
+ * queda su hash. Rotar es sobrescribir —la anterior deja de valer en el
477
+ * acto, sin ventana de gracia—, que es lo que se espera de una rotación y lo
478
+ * que la hace útil como respuesta a una fuga.
479
+ *
480
+ * ⛔ Esto es acuñar una credencial, o sea justo lo que la decisión 4 de
481
+ * `docs/DECISIONES.md` deja fuera del mapa para los integradores. Sigue
482
+ * fuera: `apps:write` es `first_party_only` y además hace falta
483
+ * `manage company`. Lo que cambia es que la primera parte, con el dueño
484
+ * dentro, hace lo que hasta hoy hacía infra editando el `.env` del host.
485
+ */
486
+ post: operations["apps.rotateCredential"];
487
+ delete?: never;
488
+ options?: never;
489
+ head?: never;
490
+ patch?: never;
491
+ trace?: never;
492
+ };
304
493
  "/crm/assignable-users": {
305
494
  parameters: {
306
495
  query?: never;
@@ -1563,6 +1752,66 @@ export interface paths {
1563
1752
  patch?: never;
1564
1753
  trace?: never;
1565
1754
  };
1755
+ "/desarrollador-link/status": {
1756
+ parameters: {
1757
+ query?: never;
1758
+ header?: never;
1759
+ path?: never;
1760
+ cookie?: never;
1761
+ };
1762
+ /**
1763
+ * GET — estado del vínculo de esta instancia
1764
+ * @description **Reservada al panel de Pimia.** Exige `admin:read`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
1765
+ */
1766
+ get: operations["desarrolladorLink.status"];
1767
+ put?: never;
1768
+ post?: never;
1769
+ delete?: never;
1770
+ options?: never;
1771
+ head?: never;
1772
+ patch?: never;
1773
+ trace?: never;
1774
+ };
1775
+ "/desarrollador-link/request": {
1776
+ parameters: {
1777
+ query?: never;
1778
+ header?: never;
1779
+ path?: never;
1780
+ cookie?: never;
1781
+ };
1782
+ get?: never;
1783
+ put?: never;
1784
+ /**
1785
+ * POST — la instancia solicita vincularse con un código DEV-XXXX-XXXX
1786
+ * @description **Reservada al panel de Pimia.** Exige `admin:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
1787
+ */
1788
+ post: operations["desarrolladorLink.request"];
1789
+ delete?: never;
1790
+ options?: never;
1791
+ head?: never;
1792
+ patch?: never;
1793
+ trace?: never;
1794
+ };
1795
+ "/desarrollador-link/revoke": {
1796
+ parameters: {
1797
+ query?: never;
1798
+ header?: never;
1799
+ path?: never;
1800
+ cookie?: never;
1801
+ };
1802
+ get?: never;
1803
+ put?: never;
1804
+ post?: never;
1805
+ /**
1806
+ * DELETE — la instancia rompe el vínculo. Siempre puede
1807
+ * @description **Reservada al panel de Pimia.** Exige `admin:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
1808
+ */
1809
+ delete: operations["desarrolladorLink.revoke"];
1810
+ options?: never;
1811
+ head?: never;
1812
+ patch?: never;
1813
+ trace?: never;
1814
+ };
1566
1815
  "/invoices/{invoice}/einvoice": {
1567
1816
  parameters: {
1568
1817
  query?: never;
@@ -5227,10 +5476,23 @@ export interface paths {
5227
5476
  * @description **Reservada al panel de Pimia.** Exige `billing:read`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
5228
5477
  *
5229
5478
  * Sin los planes de canal (`Asesoría`, `Desarrollador`): esos los contrata
5230
- * una gestoría o un desarrollador para su cartera, no una pyme. Con la
5231
- * instancia en marca blanca —su licencia la paga un desarrollador la lista
5232
- * llega VACÍA y `white_label` a `true`: el cliente vive dentro del producto
5233
- * del partner y no ve precios de Pimia. El corte va en el servidor.
5479
+ * una gestoría o un desarrollador para su cartera, no una pyme. Con
5480
+ * INTEGRADOR —su licencia la paga un desarrollador, o entró por la app de
5481
+ * uno y el vínculo sigue vivo— la lista llega VACÍA y en su lugar va
5482
+ * `catalogo`: lo que ese integrador revende, a su precio y con su enlace
5483
+ * de contratación (regla 4 del punto 12; decisión de 👤 del 2026-09-06: el
5484
+ * cliente de un integrador no ve un precio de Pimia nunca, ni antes del
5485
+ * primer pago). `white_label` sigue diciendo el HECHO de que lo paga un
5486
+ * tercero; `catalogo` es `null` mientras el integrador no configure el
5487
+ * suyo. El corte va en el servidor.
5488
+ *
5489
+ * **Cada plan dice además qué módulos opcionales trae y cuáles costarían
5490
+ * aparte** (`optional_modules`), que es lo que la pantalla de contratación
5491
+ * necesita para ofrecer añadirlos al contratar: preguntárselo a
5492
+ * `GET /tenant-modules` sería preguntar por el plan de HOY, y quien está
5493
+ * eligiendo plan quiere saber lo del plan de MAÑANA. En un plan gratuito
5494
+ * no hay ni `included` ni `addon`: no incluye ninguno y no hay
5495
+ * suscripción a la que sumarlos (2026-09-04).
5234
5496
  */
5235
5497
  get: operations["tenantBilling.plans"];
5236
5498
  put?: never;
@@ -5262,6 +5524,33 @@ export interface paths {
5262
5524
  * `usage.storage` es `null` cuando no se puede medir (esquema a medias) y
5263
5525
  * `subscription.current_period_end` es `null` cuando Stripe no contesta:
5264
5526
  * un dato que no consta se dice como tal, no se inventa un cero.
5527
+ *
5528
+ * **`addons` es lo que la suscripción paga en módulos añadidos** (desde
5529
+ * el 2026-09-04): cuántos, a cuánto, y la cuota mensual DE LISTA —plan
5530
+ * más añadidos **más integraciones**, sin prorrateos, cupones, impuestos
5531
+ * ni prueba: no es el próximo cargo— ya formateada. Existe porque el panel
5532
+ * enseñaba «Tu plan: Pimia, 12,00 € al mes» a una empresa que pagaba 14:
5533
+ * el precio del plan no es la cuota. La cantidad es la de la partida de
5534
+ * Stripe (copia local), no un recuento de filas —que contaría también los
5535
+ * heredados, que no se cobran—. `null` sin suscripción, y `null` en un
5536
+ * asiento PATROCINADO: su suscripción es la del canal, y la partida de ésa
5537
+ * la comparten todas sus instancias; la instancia no paga nada.
5538
+ *
5539
+ * **`apps` son las integraciones de pago, una a una** (desde el
5540
+ * 2026-09-05, #716), con su total propio. Salen de las partidas de la
5541
+ * suscripción, igual que la cantidad de módulos: ⛔ contar `company_apps`
5542
+ * diría de más en cuanto dos empresas de la instancia tuvieran la misma
5543
+ * —la segunda no vuelve a pagar—.
5544
+ *
5545
+ * ⛔ **Y el mismo defecto ha pasado DOS VECES en este campo.** `addons`
5546
+ * nació porque el total decía 12 y se pagaban 14 (el plan no es la cuota);
5547
+ * el 2026-09-05 decía 16 y se pagaban 25,90 (los módulos tampoco lo son).
5548
+ * Las dos veces el cálculo de los sumandos conocidos era correcto y lo que
5549
+ * faltaba era un sumando nuevo. La decisión que esto sirve —«una sola
5550
+ * cesta en el producto: el sitio donde la pyme ve lo que paga es uno»—
5551
+ * significa que **quien añada una partida de cobro tiene que sumarla en
5552
+ * `addonsPayload()`**, y que un total que no la incluya no es un total
5553
+ * incompleto: es una cifra falsa en la pantalla que la pyme lee.
5265
5554
  */
5266
5555
  get: operations["tenantBilling.subscription"];
5267
5556
  put?: never;
@@ -5296,9 +5585,19 @@ export interface paths {
5296
5585
  * `true`, `checkout_url` es `null` y `plan` dice a cuál: el panel no tiene
5297
5586
  * a dónde ir, solo refrescar.
5298
5587
  *
5588
+ * **Los módulos opcionales se pueden comprar aquí mismo** (`modules`, lista
5589
+ * de slugs): la sesión de Stripe nace con dos partidas —el plan y «Módulo
5590
+ * adicional» con tantas unidades como módulos—, y al confirmarse el pago
5591
+ * quedan encendidos y marcados como añadidos. Se validan contra el plan que
5592
+ * se contrata, no contra el actual: lo que la instancia tiene hoy no dice
5593
+ * nada de lo que tendría mañana. Lo que ofrece cada plan lo publica
5594
+ * `GET /billing/plans` en `optional_modules`.
5595
+ *
5299
5596
  * Errores, con su código en `error`: `white_label` (403), `no_payer` (409),
5300
5597
  * `free_plan` y `channel_plan` (422), `tenant_already_subscribed` (422),
5301
- * `stripe_resume_failed` (502), `stripe_price_missing` (503).
5598
+ * `invalid_addon_module` y `addon_included_in_plan` (422),
5599
+ * `stripe_resume_failed` (502), `stripe_price_missing` (503),
5600
+ * `stripe_addon_price_missing` (503).
5302
5601
  */
5303
5602
  post: operations["tenantBilling.checkoutFromPanel"];
5304
5603
  delete?: never;
@@ -5520,6 +5819,32 @@ export interface paths {
5520
5819
  * publicaba, así que el panel web enseñaba un botón de «Desactivar» sobre
5521
5820
  * `compliance-es` y otro de «Instalar» sobre `compliance-fr` en una empresa
5522
5821
  * española (épica #677).
5822
+ *
5823
+ * **Los añadidos (2026-09-03).** Un opcional que el plan NO incluye se
5824
+ * puede añadir pagando, y la respuesta lo dice con cuatro campos:
5825
+ * `billing` (`core` no se vende, `included` lo trae el plan, `addon` se
5826
+ * paga aparte), `price_cents` y `price` (lo que costaría al mes; `null` si
5827
+ * no se vende), `purchasable` (si ESTA instancia puede comprarlo ahora:
5828
+ * tiene plan de pago y quien mira es su dueño) y `addon_active` (si ya lo
5829
+ * está pagando). Con `billing: addon` y `purchasable: false` la pantalla
5830
+ * lleva a contratar un plan, que es lo que el `402 subscription_required`
5831
+ * del alta también dice.
5832
+ *
5833
+ * `available_in_plan` se conserva y ahora es «incluido o añadible»: lo que
5834
+ * la instancia puede llegar a tener.
5835
+ *
5836
+ * **Con integrador (2026-09-06, regla 4 del punto 12)** los opcionales no
5837
+ * se compran a Pimia: los activa el integrador y los cobra él. Cada
5838
+ * opcional ofrecido lleva entonces `billing: channel`, `price` es el
5839
+ * precio MINORISTA de su catálogo (`null` si no lo revende), `purchasable`
5840
+ * es falso y `contract_url` es su enlace de contratación, con `tenant` e
5841
+ * `item` puestos.
5842
+ *
5843
+ * **`addon_ends_at`** (desde el 2026-09-04, noche): un añadido dado de
5844
+ * baja no se apaga, deja de RENOVARSE — sigue encendido hasta esa fecha
5845
+ * (el fin del periodo ya pagado) y ahí se apaga. Mientras tanto
5846
+ * `addon_active` sigue en `true` (este periodo está pagado) y volver a
5847
+ * activarlo no cobra: lo «mantiene». `null` en todo lo demás.
5523
5848
  */
5524
5849
  get: operations["tenantModules.index"];
5525
5850
  put?: never;
@@ -5543,9 +5868,30 @@ export interface paths {
5543
5868
  * Instala un módulo en la instancia, y con él sus dependencias
5544
5869
  * @description **Reservada al panel de Pimia.** Exige `admin:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
5545
5870
  *
5546
- * Un módulo que no existe, uno que el plan de la instancia no incluye, o una
5547
- * dependencia que no se puede satisfacer, salen como `422` con el motivo en
5548
- * `message`.
5871
+ * Un módulo que no existe, uno que el plan de la instancia no incluye y no
5872
+ * se puede comprar, o una dependencia que no se puede satisfacer, salen
5873
+ * como `422` con el motivo en `message`.
5874
+ *
5875
+ * **Si el plan no lo incluye pero se vende** (`billing: addon`), instalarlo
5876
+ * es COMPRARLO: se cobra HOY el mes entero (una factura aparte al pagador)
5877
+ * y se suma a la suscripción de Stripe de la instancia para la
5878
+ * renovación, antes de activarlo; la fila queda marcada como añadido. Sin
5879
+ * plan de pago la respuesta es `402 subscription_required` con
5880
+ * `plan_url`; los demás cortes, con su código en `error`: `white_label`
5881
+ * (403), `not_the_payer` (403), `channel_seat` (422),
5882
+ * `stripe_price_missing` (503), `stripe_addon_failed` (502),
5883
+ * `addon_payment_failed` (402: la tarjeta no pasó; no se activa nada). Un
5884
+ * añadido que ya se está pagando no se cobra dos veces, y uno **pendiente
5885
+ * de baja** (`addon_ends_at`) se MANTIENE sin cobrar: vuelve a renovar
5886
+ * (`kept: true`, `charged: false`).
5887
+ *
5888
+ * Si el cobro entra pero el encendido revienta, la respuesta es `202` con
5889
+ * `status: pending` y `message`: el módulo se activa solo en unos minutos
5890
+ * (cola) y volver a pulsar no cobra otra vez. Otros cortes del cobro, con
5891
+ * su código: `addon_payment_requires_action` (402, el banco pide
5892
+ * confirmar y el panel aún no puede), `addon_payment_method_unsupported`
5893
+ * (402, sin tarjeta), `subscription_ending` (402, cancelada o en mora),
5894
+ * `addon_busy` (409), `addon_expired` (409).
5549
5895
  */
5550
5896
  post: operations["tenantModules.install"];
5551
5897
  delete?: never;
@@ -5564,12 +5910,28 @@ export interface paths {
5564
5910
  get?: never;
5565
5911
  put?: never;
5566
5912
  /**
5567
- * Desactiva un módulo de la instancia
5913
+ * Desactiva un módulo opcional de la instancia
5568
5914
  * @description **Reservada al panel de Pimia.** Exige `admin:write`, que el Authorization Server emite SOLO al client de primera parte: un client de integrador no puede pedir ese scope —se le rechaza en el registro y no se le anuncia— y con cualquier otro token la llamada recibe `403`. Está en el contrato porque es el panel web de Pimia quien la consume, y sus tipos salen de aquí.
5569
5915
  *
5570
- * Un módulo `core` no se puede desactivar, y tampoco uno del que dependa
5571
- * otro que siga instalado: los dos casos son `422` con el motivo en
5572
- * `message`.
5916
+ * Un básico, o un módulo del que dependa otro instalado, sale como `422`
5917
+ * con el motivo en `message`.
5918
+ *
5919
+ * **Si se estaba pagando como añadido** (fila `installed` con `meta.addon`
5920
+ * y una suscripción con partida), desactivarlo es **dejar de RENOVARLO**:
5921
+ * se resta de la partida de Stripe sin abono —el mes está pagado— y el
5922
+ * módulo SIGUE encendido hasta el fin del periodo (`addon_ends_at`); ahí
5923
+ * lo apaga `billing:apagar-anadidos-vencidos` (o la factura de
5924
+ * renovación). La respuesta lo dice: `status: installed`, `addon_released:
5925
+ * true`, `addon_ends_at`. Uno ya pendiente no cambia. Si Stripe no
5926
+ * contesta, el módulo sigue encendido y renovando: `502
5927
+ * stripe_addon_release_failed` o `stripe_period_unknown`.
5928
+ *
5929
+ * Un heredado (encendido sin marca) o un añadido sin partida se apaga en
5930
+ * el acto, como siempre: no hay nada pagado que respetar.
5931
+ *
5932
+ * **Un módulo activado por el integrador** (`meta.channel`, lo paga su
5933
+ * canal) no lo apaga el cliente: `403 channel_module`, con el nombre del
5934
+ * integrador en `message`.
5573
5935
  */
5574
5936
  post: operations["tenantModules.disable"];
5575
5937
  delete?: never;
@@ -11031,90 +11393,482 @@ export interface operations {
11031
11393
  };
11032
11394
  content: {
11033
11395
  "application/json": {
11034
- success: boolean;
11396
+ success: boolean;
11397
+ };
11398
+ };
11399
+ };
11400
+ 404: components["responses"]["ModelNotFoundException"];
11401
+ };
11402
+ };
11403
+ "approvals.store": {
11404
+ parameters: {
11405
+ query?: never;
11406
+ header?: never;
11407
+ path?: never;
11408
+ cookie?: never;
11409
+ };
11410
+ requestBody: {
11411
+ content: {
11412
+ "application/json": components["schemas"]["StoreApprovalRequest"];
11413
+ };
11414
+ };
11415
+ responses: {
11416
+ 201: {
11417
+ headers: {
11418
+ [name: string]: unknown;
11419
+ };
11420
+ content: {
11421
+ "application/json": {
11422
+ approval: {
11423
+ id: number;
11424
+ plane: string;
11425
+ title: string;
11426
+ task_type: string | null;
11427
+ context: unknown[] | null;
11428
+ /**
11429
+ * @description pending|in_progress|completed|failed — para el partner:
11430
+ * in_progress = pendiente de decisión; completed = aprobada;
11431
+ * failed = rechazada.
11432
+ */
11433
+ status: string;
11434
+ proposal: unknown[] | null;
11435
+ /**
11436
+ * @description proposed|needs_changes|approved|rejected. `needs_changes` NO es
11437
+ * terminal: el owner pidió una revisión — en v1 el partner remite
11438
+ * una propuesta nueva (no hay PATCH) o espera la decisión.
11439
+ */
11440
+ proposal_status: string | null;
11441
+ result: string | null;
11442
+ proposed_at: string;
11443
+ created_at: string;
11444
+ updated_at: string;
11445
+ };
11446
+ };
11447
+ };
11448
+ };
11449
+ 403: {
11450
+ headers: {
11451
+ [name: string]: unknown;
11452
+ };
11453
+ content: {
11454
+ "application/json": {
11455
+ /** @constant */
11456
+ message: "Este endpoint exige un token OAuth de app de partner con el scope approvals:write.";
11457
+ };
11458
+ };
11459
+ };
11460
+ 409: {
11461
+ headers: {
11462
+ [name: string]: unknown;
11463
+ };
11464
+ content: {
11465
+ "application/json": {
11466
+ /** @constant */
11467
+ message: "No hay un tenant en contexto para esta propuesta.";
11468
+ };
11469
+ };
11470
+ };
11471
+ 422: components["responses"]["ValidationException"];
11472
+ };
11473
+ };
11474
+ "approvals.show": {
11475
+ parameters: {
11476
+ query?: never;
11477
+ header?: never;
11478
+ path: {
11479
+ id: number;
11480
+ };
11481
+ cookie?: never;
11482
+ };
11483
+ requestBody?: never;
11484
+ responses: {
11485
+ 200: {
11486
+ headers: {
11487
+ [name: string]: unknown;
11488
+ };
11489
+ content: {
11490
+ "application/json": {
11491
+ approval: {
11492
+ id: number;
11493
+ plane: string;
11494
+ title: string;
11495
+ task_type: string | null;
11496
+ context: unknown[] | null;
11497
+ /**
11498
+ * @description pending|in_progress|completed|failed — para el partner:
11499
+ * in_progress = pendiente de decisión; completed = aprobada;
11500
+ * failed = rechazada.
11501
+ */
11502
+ status: string;
11503
+ proposal: unknown[] | null;
11504
+ /**
11505
+ * @description proposed|needs_changes|approved|rejected. `needs_changes` NO es
11506
+ * terminal: el owner pidió una revisión — en v1 el partner remite
11507
+ * una propuesta nueva (no hay PATCH) o espera la decisión.
11508
+ */
11509
+ proposal_status: string | null;
11510
+ result: string | null;
11511
+ proposed_at: string;
11512
+ created_at: string;
11513
+ updated_at: string;
11514
+ };
11515
+ };
11516
+ };
11517
+ };
11518
+ 403: {
11519
+ headers: {
11520
+ [name: string]: unknown;
11521
+ };
11522
+ content: {
11523
+ "application/json": {
11524
+ /** @constant */
11525
+ message: "Este endpoint exige un token OAuth de app de partner con el scope approvals:write.";
11526
+ };
11527
+ };
11528
+ };
11529
+ 409: {
11530
+ headers: {
11531
+ [name: string]: unknown;
11532
+ };
11533
+ content: {
11534
+ "application/json": {
11535
+ /** @constant */
11536
+ message: "No hay un tenant en contexto para esta propuesta.";
11537
+ };
11538
+ };
11539
+ };
11540
+ };
11541
+ };
11542
+ "apps.index": {
11543
+ parameters: {
11544
+ query?: never;
11545
+ header?: never;
11546
+ path?: never;
11547
+ cookie?: never;
11548
+ };
11549
+ requestBody?: never;
11550
+ responses: {
11551
+ 200: {
11552
+ headers: {
11553
+ [name: string]: unknown;
11554
+ };
11555
+ content: {
11556
+ "application/json": {
11557
+ apps: {
11558
+ slug: string;
11559
+ name: string;
11560
+ description: string | null;
11561
+ publisher: string | null;
11562
+ kind: string;
11563
+ install: string[];
11564
+ scopes: string[];
11565
+ webhook_events: string[];
11566
+ config_url: string | null;
11567
+ price_cents: number | null;
11568
+ listed: boolean;
11569
+ status: string;
11570
+ installed: boolean;
11571
+ installed_at: string | null;
11572
+ disabled_at: string | null;
11573
+ installed_by: {
11574
+ id: number;
11575
+ name: string | null;
11576
+ } | null;
11577
+ authorization: {
11578
+ id: number;
11579
+ revoked: boolean;
11580
+ last_used_at: string | null;
11581
+ } | null;
11582
+ missing_required: string[];
11583
+ entry_credential: {
11584
+ set: boolean;
11585
+ last_four: string | null;
11586
+ created_at: string | null;
11587
+ last_used_at: string | null;
11588
+ };
11589
+ }[];
11590
+ installed_slugs: string[];
11591
+ };
11592
+ };
11593
+ };
11594
+ };
11595
+ };
11596
+ "apps.show": {
11597
+ parameters: {
11598
+ query?: never;
11599
+ header?: never;
11600
+ path: {
11601
+ slug: string;
11602
+ };
11603
+ cookie?: never;
11604
+ };
11605
+ requestBody?: never;
11606
+ responses: {
11607
+ 200: {
11608
+ headers: {
11609
+ [name: string]: unknown;
11610
+ };
11611
+ content: {
11612
+ "application/json": {
11613
+ app: {
11614
+ slug: string;
11615
+ name: string;
11616
+ description: string | null;
11617
+ publisher: string | null;
11618
+ kind: string;
11619
+ install: string[];
11620
+ scopes: string[];
11621
+ webhook_events: string[];
11622
+ config_url: string | null;
11623
+ price_cents: number | null;
11624
+ listed: boolean;
11625
+ status: string;
11626
+ installed: boolean;
11627
+ installed_at: string | null;
11628
+ disabled_at: string | null;
11629
+ installed_by: {
11630
+ id: number;
11631
+ name: string | null;
11632
+ } | null;
11633
+ authorization: {
11634
+ id: number;
11635
+ revoked: boolean;
11636
+ last_used_at: string | null;
11637
+ } | null;
11638
+ missing_required: string[];
11639
+ entry_credential: {
11640
+ set: boolean;
11641
+ last_four: string | null;
11642
+ created_at: string | null;
11643
+ last_used_at: string | null;
11644
+ };
11645
+ config_schema: {
11646
+ [key: string]: {
11647
+ type: string;
11648
+ required: boolean;
11649
+ secret: boolean;
11650
+ };
11651
+ };
11652
+ config: {
11653
+ [key: string]: unknown;
11654
+ };
11655
+ };
11656
+ };
11657
+ };
11658
+ };
11659
+ };
11660
+ };
11661
+ "apps.install": {
11662
+ parameters: {
11663
+ query?: never;
11664
+ header?: never;
11665
+ path: {
11666
+ slug: string;
11667
+ };
11668
+ cookie?: never;
11669
+ };
11670
+ requestBody?: {
11671
+ content: {
11672
+ "application/json": {
11673
+ webhook_url?: string | null;
11674
+ };
11675
+ };
11676
+ };
11677
+ responses: {
11678
+ 200: {
11679
+ headers: {
11680
+ [name: string]: unknown;
11681
+ };
11682
+ content: {
11683
+ "application/json": {
11684
+ app: {
11685
+ slug: string;
11686
+ name: string;
11687
+ description: string | null;
11688
+ publisher: string | null;
11689
+ kind: string;
11690
+ install: string[];
11691
+ scopes: string[];
11692
+ webhook_events: string[];
11693
+ config_url: string | null;
11694
+ price_cents: number | null;
11695
+ listed: boolean;
11696
+ status: string;
11697
+ installed: boolean;
11698
+ installed_at: string | null;
11699
+ disabled_at: string | null;
11700
+ installed_by: {
11701
+ id: number;
11702
+ name: string | null;
11703
+ } | null;
11704
+ authorization: {
11705
+ id: number;
11706
+ revoked: boolean;
11707
+ last_used_at: string | null;
11708
+ } | null;
11709
+ missing_required: string[];
11710
+ entry_credential: {
11711
+ set: boolean;
11712
+ last_four: string | null;
11713
+ created_at: string | null;
11714
+ last_used_at: string | null;
11715
+ };
11716
+ };
11717
+ webhook_secret?: string;
11718
+ entry_credential?: string;
11719
+ billing: {
11720
+ ok: boolean;
11721
+ charged?: boolean;
11722
+ already_paid?: boolean;
11723
+ free?: boolean;
11724
+ invoice?: string;
11725
+ };
11726
+ };
11727
+ };
11728
+ };
11729
+ 422: components["responses"]["ValidationException"];
11730
+ };
11731
+ };
11732
+ "apps.uninstall": {
11733
+ parameters: {
11734
+ query?: never;
11735
+ header?: never;
11736
+ path: {
11737
+ slug: string;
11738
+ };
11739
+ cookie?: never;
11740
+ };
11741
+ requestBody?: never;
11742
+ responses: {
11743
+ 200: {
11744
+ headers: {
11745
+ [name: string]: unknown;
11746
+ };
11747
+ content: {
11748
+ "application/json": {
11749
+ app: {
11750
+ slug: string;
11751
+ name: string;
11752
+ description: string | null;
11753
+ publisher: string | null;
11754
+ kind: string;
11755
+ install: string[];
11756
+ scopes: string[];
11757
+ webhook_events: string[];
11758
+ config_url: string | null;
11759
+ price_cents: number | null;
11760
+ listed: boolean;
11761
+ status: string;
11762
+ installed: boolean;
11763
+ installed_at: string | null;
11764
+ disabled_at: string | null;
11765
+ installed_by: {
11766
+ id: number;
11767
+ name: string | null;
11768
+ } | null;
11769
+ authorization: {
11770
+ id: number;
11771
+ revoked: boolean;
11772
+ last_used_at: string | null;
11773
+ } | null;
11774
+ missing_required: string[];
11775
+ entry_credential: {
11776
+ set: boolean;
11777
+ last_four: string | null;
11778
+ created_at: string | null;
11779
+ last_used_at: string | null;
11780
+ };
11781
+ };
11782
+ revoked_tokens: number;
11783
+ webhooks_removed: number;
11784
+ config_kept: boolean;
11785
+ billing: {
11786
+ ok: boolean;
11787
+ released?: boolean;
11788
+ kept_for_others?: boolean;
11789
+ free?: boolean;
11790
+ nothing_to_release?: boolean;
11791
+ release_failed?: boolean;
11792
+ paid_until?: string | null;
11793
+ };
11794
+ };
11795
+ };
11796
+ };
11797
+ };
11798
+ };
11799
+ "apps.config": {
11800
+ parameters: {
11801
+ query?: never;
11802
+ header?: never;
11803
+ path: {
11804
+ slug: string;
11805
+ };
11806
+ cookie?: never;
11807
+ };
11808
+ requestBody?: never;
11809
+ responses: {
11810
+ 200: {
11811
+ headers: {
11812
+ [name: string]: unknown;
11813
+ };
11814
+ content: {
11815
+ "application/json": {
11816
+ config: {
11817
+ [key: string]: unknown;
11818
+ };
11819
+ config_schema: {
11820
+ [key: string]: {
11821
+ type: string;
11822
+ required: boolean;
11823
+ secret: boolean;
11824
+ };
11825
+ };
11826
+ missing_required: string[];
11035
11827
  };
11036
11828
  };
11037
11829
  };
11038
- 404: components["responses"]["ModelNotFoundException"];
11039
11830
  };
11040
11831
  };
11041
- "approvals.store": {
11832
+ "apps.updateConfig": {
11042
11833
  parameters: {
11043
11834
  query?: never;
11044
11835
  header?: never;
11045
- path?: never;
11046
- cookie?: never;
11047
- };
11048
- requestBody: {
11049
- content: {
11050
- "application/json": components["schemas"]["StoreApprovalRequest"];
11836
+ path: {
11837
+ slug: string;
11051
11838
  };
11839
+ cookie?: never;
11052
11840
  };
11841
+ requestBody?: never;
11053
11842
  responses: {
11054
- 201: {
11843
+ 200: {
11055
11844
  headers: {
11056
11845
  [name: string]: unknown;
11057
11846
  };
11058
11847
  content: {
11059
11848
  "application/json": {
11060
- approval: {
11061
- id: number;
11062
- plane: string;
11063
- title: string;
11064
- task_type: string | null;
11065
- context: unknown[] | null;
11066
- /**
11067
- * @description pending|in_progress|completed|failed — para el partner:
11068
- * in_progress = pendiente de decisión; completed = aprobada;
11069
- * failed = rechazada.
11070
- */
11071
- status: string;
11072
- proposal: unknown[] | null;
11073
- /**
11074
- * @description proposed|needs_changes|approved|rejected. `needs_changes` NO es
11075
- * terminal: el owner pidió una revisión — en v1 el partner remite
11076
- * una propuesta nueva (no hay PATCH) o espera la decisión.
11077
- */
11078
- proposal_status: string | null;
11079
- result: string | null;
11080
- proposed_at: string;
11081
- created_at: string;
11082
- updated_at: string;
11849
+ config: {
11850
+ [key: string]: unknown;
11083
11851
  };
11084
- };
11085
- };
11086
- };
11087
- 403: {
11088
- headers: {
11089
- [name: string]: unknown;
11090
- };
11091
- content: {
11092
- "application/json": {
11093
- /** @constant */
11094
- message: "Este endpoint exige un token OAuth de app de partner con el scope approvals:write.";
11095
- };
11096
- };
11097
- };
11098
- 409: {
11099
- headers: {
11100
- [name: string]: unknown;
11101
- };
11102
- content: {
11103
- "application/json": {
11104
- /** @constant */
11105
- message: "No hay un tenant en contexto para esta propuesta.";
11852
+ config_schema: {
11853
+ [key: string]: {
11854
+ type: string;
11855
+ required: boolean;
11856
+ secret: boolean;
11857
+ };
11858
+ };
11859
+ missing_required: string[];
11106
11860
  };
11107
11861
  };
11108
11862
  };
11109
11863
  422: components["responses"]["ValidationException"];
11110
11864
  };
11111
11865
  };
11112
- "approvals.show": {
11866
+ "apps.rotateCredential": {
11113
11867
  parameters: {
11114
11868
  query?: never;
11115
11869
  header?: never;
11116
11870
  path: {
11117
- id: number;
11871
+ slug: string;
11118
11872
  };
11119
11873
  cookie?: never;
11120
11874
  };
@@ -11126,52 +11880,8 @@ export interface operations {
11126
11880
  };
11127
11881
  content: {
11128
11882
  "application/json": {
11129
- approval: {
11130
- id: number;
11131
- plane: string;
11132
- title: string;
11133
- task_type: string | null;
11134
- context: unknown[] | null;
11135
- /**
11136
- * @description pending|in_progress|completed|failed — para el partner:
11137
- * in_progress = pendiente de decisión; completed = aprobada;
11138
- * failed = rechazada.
11139
- */
11140
- status: string;
11141
- proposal: unknown[] | null;
11142
- /**
11143
- * @description proposed|needs_changes|approved|rejected. `needs_changes` NO es
11144
- * terminal: el owner pidió una revisión — en v1 el partner remite
11145
- * una propuesta nueva (no hay PATCH) o espera la decisión.
11146
- */
11147
- proposal_status: string | null;
11148
- result: string | null;
11149
- proposed_at: string;
11150
- created_at: string;
11151
- updated_at: string;
11152
- };
11153
- };
11154
- };
11155
- };
11156
- 403: {
11157
- headers: {
11158
- [name: string]: unknown;
11159
- };
11160
- content: {
11161
- "application/json": {
11162
- /** @constant */
11163
- message: "Este endpoint exige un token OAuth de app de partner con el scope approvals:write.";
11164
- };
11165
- };
11166
- };
11167
- 409: {
11168
- headers: {
11169
- [name: string]: unknown;
11170
- };
11171
- content: {
11172
- "application/json": {
11173
- /** @constant */
11174
- message: "No hay un tenant en contexto para esta propuesta.";
11883
+ entry_credential: string;
11884
+ app: string;
11175
11885
  };
11176
11886
  };
11177
11887
  };
@@ -13772,6 +14482,121 @@ export interface operations {
13772
14482
  };
13773
14483
  };
13774
14484
  };
14485
+ "desarrolladorLink.status": {
14486
+ parameters: {
14487
+ query?: never;
14488
+ header?: never;
14489
+ path?: never;
14490
+ cookie?: never;
14491
+ };
14492
+ requestBody?: never;
14493
+ responses: {
14494
+ 200: {
14495
+ headers: {
14496
+ [name: string]: unknown;
14497
+ };
14498
+ content: {
14499
+ "application/json": {
14500
+ data: {
14501
+ id: number;
14502
+ status: string;
14503
+ link_code: string;
14504
+ /** Format: date-time */
14505
+ requested_at: string | null;
14506
+ /** Format: date-time */
14507
+ accepted_at: string | null;
14508
+ desarrollador: {
14509
+ id: string | null;
14510
+ name: string | null;
14511
+ email: string | null;
14512
+ };
14513
+ /**
14514
+ * @description Lo que el dueño de la instancia debe tener claro al vincular.
14515
+ * @constant
14516
+ */
14517
+ alcance: "Este vínculo es administrativo y de facturación. No da acceso a tus datos: eso lo autorizas tú desde «Apps conectadas», permiso a permiso.";
14518
+ } | {
14519
+ /** @constant */
14520
+ status: "none";
14521
+ };
14522
+ };
14523
+ };
14524
+ };
14525
+ 404: components["responses"]["ModelNotFoundException"];
14526
+ };
14527
+ };
14528
+ "desarrolladorLink.request": {
14529
+ parameters: {
14530
+ query?: never;
14531
+ header?: never;
14532
+ path?: never;
14533
+ cookie?: never;
14534
+ };
14535
+ requestBody: {
14536
+ content: {
14537
+ "application/json": {
14538
+ link_code: string;
14539
+ };
14540
+ };
14541
+ };
14542
+ responses: {
14543
+ 201: {
14544
+ headers: {
14545
+ [name: string]: unknown;
14546
+ };
14547
+ content: {
14548
+ "application/json": {
14549
+ /** @constant */
14550
+ message: "Solicitud enviada al desarrollador.";
14551
+ data: {
14552
+ id: number;
14553
+ status: string;
14554
+ link_code: string;
14555
+ /** Format: date-time */
14556
+ requested_at: string | null;
14557
+ /** Format: date-time */
14558
+ accepted_at: string | null;
14559
+ desarrollador: {
14560
+ id: string | null;
14561
+ name: string | null;
14562
+ email: string | null;
14563
+ };
14564
+ /**
14565
+ * @description Lo que el dueño de la instancia debe tener claro al vincular.
14566
+ * @constant
14567
+ */
14568
+ alcance: "Este vínculo es administrativo y de facturación. No da acceso a tus datos: eso lo autorizas tú desde «Apps conectadas», permiso a permiso.";
14569
+ };
14570
+ };
14571
+ };
14572
+ };
14573
+ 404: components["responses"]["ModelNotFoundException"];
14574
+ 422: components["responses"]["ValidationException"];
14575
+ };
14576
+ };
14577
+ "desarrolladorLink.revoke": {
14578
+ parameters: {
14579
+ query?: never;
14580
+ header?: never;
14581
+ path?: never;
14582
+ cookie?: never;
14583
+ };
14584
+ requestBody?: never;
14585
+ responses: {
14586
+ 200: {
14587
+ headers: {
14588
+ [name: string]: unknown;
14589
+ };
14590
+ content: {
14591
+ "application/json": {
14592
+ /** @constant */
14593
+ message: "Vinculación revocada.";
14594
+ };
14595
+ };
14596
+ };
14597
+ 404: components["responses"]["ModelNotFoundException"];
14598
+ };
14599
+ };
13775
14600
  "eInvoice.download": {
13776
14601
  parameters: {
13777
14602
  query?: {
@@ -21920,9 +22745,36 @@ export interface operations {
21920
22745
  max_storage_mb: number;
21921
22746
  features: string[];
21922
22747
  is_free: boolean;
22748
+ optional_modules: {
22749
+ slug: string;
22750
+ name: string;
22751
+ description: string | null;
22752
+ included: boolean;
22753
+ addon: boolean;
22754
+ price_cents: number | null;
22755
+ price: string | null;
22756
+ }[];
21923
22757
  }[];
21924
22758
  white_label: boolean;
21925
22759
  message: string | null;
22760
+ catalogo: {
22761
+ integrador: {
22762
+ nombre: string;
22763
+ soporte_url: string | null;
22764
+ soporte_email: string | null;
22765
+ };
22766
+ currency: string;
22767
+ items: {
22768
+ kind: string;
22769
+ slug: string;
22770
+ name: string;
22771
+ description: string | null;
22772
+ price_cents: number;
22773
+ price: string;
22774
+ contract_url: string | null;
22775
+ active: boolean | null;
22776
+ }[];
22777
+ } | null;
21926
22778
  };
21927
22779
  };
21928
22780
  };
@@ -21980,6 +22832,11 @@ export interface operations {
21980
22832
  mode: string;
21981
22833
  white_label: boolean;
21982
22834
  can_manage: boolean;
22835
+ integrador: {
22836
+ nombre: string;
22837
+ soporte_url: string | null;
22838
+ soporte_email: string | null;
22839
+ } | null;
21983
22840
  seat: {
21984
22841
  role: string;
21985
22842
  grace_until: string | null;
@@ -21992,6 +22849,24 @@ export interface operations {
21992
22849
  cancel_at_period_end: boolean;
21993
22850
  ends_at: string | null;
21994
22851
  } | null;
22852
+ apps: {
22853
+ items: {
22854
+ slug: string;
22855
+ name: string;
22856
+ price_cents: number;
22857
+ price: string;
22858
+ quantity: number;
22859
+ }[];
22860
+ total_cents: number;
22861
+ total: string;
22862
+ } | null;
22863
+ addons: {
22864
+ quantity: number;
22865
+ price_cents: number;
22866
+ price: string;
22867
+ total_cents: number;
22868
+ total: string;
22869
+ } | null;
21995
22870
  status: string;
21996
22871
  };
21997
22872
  };
@@ -22007,7 +22882,14 @@ export interface operations {
22007
22882
  path?: never;
22008
22883
  cookie?: never;
22009
22884
  };
22010
- requestBody?: never;
22885
+ requestBody: {
22886
+ content: {
22887
+ "application/json": {
22888
+ plan_id: number;
22889
+ modules?: string[];
22890
+ };
22891
+ };
22892
+ };
22011
22893
  responses: {
22012
22894
  200: {
22013
22895
  headers: {
@@ -22019,10 +22901,14 @@ export interface operations {
22019
22901
  checkout_url: string | null;
22020
22902
  resumed: boolean;
22021
22903
  plan: string | null;
22904
+ addons: string[];
22905
+ addons_failed: boolean;
22906
+ addons_message: string | null;
22022
22907
  };
22023
22908
  };
22024
22909
  };
22025
22910
  };
22911
+ 422: components["responses"]["ValidationException"];
22026
22912
  };
22027
22913
  };
22028
22914
  "tenantBilling.portal": {
@@ -22422,6 +23308,13 @@ export interface operations {
22422
23308
  abilities_namespace: string | null;
22423
23309
  status: string;
22424
23310
  available_in_plan: boolean;
23311
+ billing: string;
23312
+ price_cents: number | null;
23313
+ price: string | null;
23314
+ purchasable: boolean;
23315
+ contract_url: string | null;
23316
+ addon_active: boolean;
23317
+ addon_ends_at: string | null;
22425
23318
  installed_at: string | null;
22426
23319
  disabled_at: string | null;
22427
23320
  version: string | null;
@@ -22431,6 +23324,12 @@ export interface operations {
22431
23324
  dependents: string[];
22432
23325
  }[];
22433
23326
  installed_slugs: string[];
23327
+ addons: {
23328
+ price_cents: number;
23329
+ price: string;
23330
+ quantity: number;
23331
+ purchasable: boolean;
23332
+ };
22434
23333
  };
22435
23334
  };
22436
23335
  };
@@ -22461,6 +23360,9 @@ export interface operations {
22461
23360
  status: string;
22462
23361
  installed_at: string | null;
22463
23362
  installed_slugs: string[];
23363
+ addon: boolean;
23364
+ charged: boolean;
23365
+ kept: boolean;
22464
23366
  };
22465
23367
  };
22466
23368
  };
@@ -22489,6 +23391,8 @@ export interface operations {
22489
23391
  status: string;
22490
23392
  disabled_at: string | null;
22491
23393
  installed_slugs: string[];
23394
+ addon_released: boolean;
23395
+ addon_ends_at: string | null;
22492
23396
  };
22493
23397
  };
22494
23398
  };