diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..06c3e1f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,25 @@ +# Keep generated artifacts tracked, but collapse their diffs on GitHub. +src/generated/contracts.ts linguist-generated=true +src/generated/dates.ts linguist-generated=true +src/generated/input.ts linguist-generated=true +src/generated/models.ts linguist-generated=true +src/generated/output.ts linguist-generated=true +src/resources/customers.ts linguist-generated=true +src/resources/invoices.ts linguist-generated=true +src/resources/organizations.ts linguist-generated=true +src/resources/products.ts linguist-generated=true +src/resources/receipts.ts linguist-generated=true +src/resources/retentions.ts linguist-generated=true +src/tools/cartaPorteCatalogs.ts linguist-generated=true +src/tools/catalogs.ts linguist-generated=true +src/tools/comercioExteriorCatalogs.ts linguist-generated=true +src/tools/tools.ts linguist-generated=true +src/tools/webhooks.ts linguist-generated=true +src/types/common.ts linguist-generated=true +src/types/complements.ts linguist-generated=true +src/types/customer.ts linguist-generated=true +src/types/invoice.ts linguist-generated=true +src/types/organization.ts linguist-generated=true +src/types/product.ts linguist-generated=true +src/types/receipt.ts linguist-generated=true +src/types/retention.ts linguist-generated=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b66753..7659d6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,9 @@ jobs: - name: Build package run: pnpm run build + - name: Verify generated SDK + run: pnpm run generate:sdk:check + - name: Upload dist artifact uses: actions/upload-artifact@v7 with: @@ -56,7 +59,7 @@ jobs: path: dist - name: Run Node 18 runtime compatibility smoke - run: node --test test/compat/node18-compat.test.cjs + run: node --test test/compat/*.test.cjs test/compat/*.test.mjs node-runtime: runs-on: ubuntu-latest @@ -125,6 +128,9 @@ jobs: - name: Run type contract tests run: pnpm run test:types + - name: Lint + run: pnpm run lint + browser-smoke: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index 24d035a..abf9016 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ test.js lib/ dist/ +test-results/ +playwright-report/ # Created by https://www.gitignore.io/api/node,macos,linux,windows,visualstudiocode diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..2b21a65 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +dist/ +coverage/ +test-results/ +playwright-report/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..51d5f17 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,30 @@ +# Contributor instructions + +## Consumer documentation + +- Write `CHANGELOG.md` for developers who consume the SDK. Document observable behavior, public API and type changes, compatibility requirements, fixes, and any action required to upgrade. +- Keep build tools, bundlers, test runners, lint/format configuration, CI setup, and development-only dependency updates out of the changelog. Explain those in pull request descriptions instead. +- Summarize type changes by consumer capability or correction, not by individual fields or implementation steps. Put detailed upgrade cases in the README migration guide. +- Keep changelog entries factual and concise. Use a friendly, task-oriented tone in the README; occasional emojis belong there, not in new changelog entries. +- Preserve published changelog entries as written. Apply editorial changes only to new entries; correct historical entries only when a concrete factual error has been verified. +- Keep migration guidance in the README. State which integrations need no code changes as explicitly as those that do. Verify historical behavior against released source before documenting a migration; do not infer a breaking change from a version number alone. + +## OpenAPI generation + +- Generate resource methods, request/response types, model aliases, and response date plans with `pnpm generate:sdk`. Do not edit files carrying a generation banner. +- `openapi/source.json` pins a complete public FacturAPI/facturapi-docs commit SHA. `pnpm sync:openapi` resolves docs `main` to its current commit, downloads the spec from that exact commit, and records it only after parsing succeeds. An explicit public branch, tag or full SHA is supported for coordinated PRs. Run `pnpm generate:sdk` after syncing. +- Generation always downloads the YAML from the recorded commit into memory; it never follows a moving branch or writes a spec snapshot. Builds and runtime tests use tracked generated files and need no spec download. Commit public documentation changes and sync their public ref before generating; do not record local filesystem paths or pin unpublished local changes. +- Generate method summaries, argument descriptions and return documentation from OpenAPI. Keep SDK-specific binary upload/download and local webhook verification guidance in the generator; attach documentation to every public overload and use absolute documentation links. +- `openapi-typescript` resolves the OpenAPI contract; the TypeScript compiler resolves the resulting types for date plans. Do not add a second JSON Schema interpreter or a handwritten date-path inventory. +- `scripts/sdk/resources.json` maps public resource/method names to operation IDs. Use a string operation ID for normal endpoints; HTTP bindings and signatures are derived from the spec. Add overrides only for established argument names, optionality/nullability, fixed download formats, multipart/local-signature behavior, or response overloads. Do not repeat inferred path/body/query bindings. Every public HTTP operation must have a binding; adding an operation intentionally fails generation until its public method is chosen. +- Use `bodySchema` for an explicit SDK convenience method that selects a specific input variant from the public spec while preserving the original HTTP operation. Keep `create()` available for dynamic or incomplete customer inputs; do not add runtime validation or rewrite the supplied body. +- Use `querySchema` to bind a grouped query contract from the public spec when separate OpenAPI query parameters cannot express dependencies between them. Keep conditional values and required fields in that schema rather than repeating them in generator code. TypeScript cannot express arbitrary string exclusions (`not`); do not invent a narrower country catalog to work around that limitation. +- Use `bodyByQueryFlag` only for a verified relationship between a query flag and an input schema that OpenAPI cannot express across parameters and request bodies. Keep both input schemas in the public spec; require a literal `true` to select the incomplete body and preserve the normal input for dynamic booleans. +- Preserve the SDK convention that a declared request body is a required method argument unless the operation explicitly marks it optional (`required: false`) or a compatibility override says otherwise. Optional query objects accept null by default; explicit overrides preserve existing exceptions. +- `scripts/sdk/models.json` preserves public model names. `scripts/sdk/enums.json` binds existing runtime enums to their semantic schema locations; never bind enums merely because their numeric/string values happen to match. Named enum drift must be corrected explicitly. +- Preserve the real HTTP transport, binary behavior, and local cryptography. Test external HTTP boundaries with fixtures; do not replace these implementations with mocks. +- Run `pnpm generate:sdk:check`, `pnpm test`, `pnpm lint`, and browser tests for generation changes. Cover input strings/Date values, nullable dates, complement discriminants, opaque metadata/XML, and additions to the contract. +- This repository is public. Never copy private implementation sources, paths, identifiers, diagnostics, or planning context into generated files, tests, commits, PR descriptions, or review replies. +- Keep the source commit metadata and generated sources tracked; do not commit a downloaded spec. Mark generated artifacts with `linguist-generated` in `.gitattributes` so reviews focus on the generator, bindings, runtime, and tests; keep handwritten configuration visible. Update the attributes when adding generated output files. + +- Describe current SDK capabilities in the README without release announcements ; version references are appropriate when they explain verified compatibility or when a capability became available. Put release improvements in the changelog. The SDK supports Node.js and browsers; keep titles and summaries accurate for both. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad41ee..db96cb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [6.0.0] Unreleased + +### Breaking + +- Response timestamps are consistently returned as `Date` objects. SAT stamp timestamps and calendar dates remain strings. +- Request and response types now follow the API contract, with more precise CFDI and complement inputs. TypeScript integrations may need adjustments; see the [migration guide from v3, v4, and v5](README.md#actualizar-desde-v3-v4-o-v5). +- Import from `facturapi`; direct imports into internal package files such as `facturapi/dist/...` are no longer supported. + +### Fixed + +- Correct request typing for partial product updates and native Node.js file uploads. +- Webhook signature validation consistently returns parsed events with converted dates in Node.js and browsers. + +### Added + +- Autocompletion and editor documentation for request fields, method arguments, and responses across SDK operations. +- More precise input types for CFDI variants, drafts, structured complements, and customer creation. Related fields are checked by TypeScript in supported cases, helping catch incomplete or incompatible inputs before sending a request. +- Receipt invoicing distinguishes invoice creation from `dry_run` summaries in its return types. +- Methods to create national, foreign, and generic RFC customers with specific input types; assign receipt customers; upload FIEL certificates; and check API health. +- CommonJS supports `const Facturapi = require('facturapi')` directly, while retaining `.default` compatibility. CommonJS and ESM include matching TypeScript definitions. + ## [5.1.0] 2026-09-12 ### Added diff --git a/README.md b/README.md index 115f762..8b45675 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,283 @@ -# FacturAPI +# Facturapi para JavaScript y TypeScript -[![npm version](https://badge.fury.io/js/facturapi.svg)](https://badge.fury.io/js/facturapi) +[![npm](https://img.shields.io/npm/v/facturapi)](https://www.npmjs.com/package/facturapi) [![CI](https://github.com/FacturAPI/facturapi-node/actions/workflows/ci.yml/badge.svg)](https://github.com/FacturAPI/facturapi-node/actions/workflows/ci.yml) -![TypeScript](https://img.shields.io/badge/TypeScript-Ready-3178C6?logo=typescript&logoColor=white) +[![Licencia MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE) -Official HTTP client for [FacturAPI](https://www.facturapi.io). +Integra facturación electrónica en México desde Node.js o navegadores, con JavaScript o TypeScript. Crea CFDI, entrega sus archivos PDF y XML y administra clientes, productos y organizaciones con el SDK oficial de [Facturapi](https://www.facturapi.io). -FacturAPI helps developers generate valid electronic invoices (CFDI) in Mexico. +[Documentación](https://docs.facturapi.io) · [Referencia de la API](https://docs.facturapi.io/api/) · [Crear una cuenta](https://www.facturapi.io/register) · [Changelog](CHANGELOG.md) -If you've used [Stripe](https://stripe.com) or [Conekta](https://conekta.io), you'll find the API style familiar. +## Tu primera factura de prueba 🚀 -## Compatibility +Vamos a crear una factura de prueba. Necesitas Node.js 18 o superior y la **Test Secret Key de una organización**, que encontrarás en tu cuenta de Facturapi. Guárdala en la variable de entorno `FACTURAPI_KEY`. -| Runtime | Support | -| --- | --- | -| Node.js | `>=18` (CI tested on 18, 20, 22, 24) | -| Browser | Environments with `fetch`, `FormData`, and `Blob` | -| React Native | Versions that provide global `fetch`, `FormData`, and `Blob` | +Puedes empezar sin una suscripción: las facturas del ambiente Test no se envían al SAT ni tienen validez fiscal. Primero, instala el SDK: -## Install - -```bash -npm i facturapi +```sh +npm install facturapi ``` -## TypeScript +También puedes instalarlo con `pnpm add facturapi` o `yarn add facturapi`. -This SDK is TypeScript-first and exports its public types. +Guarda lo siguiente en `primera-factura.mjs`. Los datos del receptor son ficticios para este ejemplo en ambiente Test. No necesitas crear previamente un cliente o un producto: puedes incluir sus datos en la misma petición. -## Getting started +```js +import Facturapi, { PaymentForm } from 'facturapi' -Make sure you have a FacturAPI account and your API key. +const facturapi = new Facturapi(process.env.FACTURAPI_KEY) -```ts -import Facturapi from 'facturapi'; +const invoice = await facturapi.invoices.create({ + customer: { + legal_name: 'Cliente de prueba', + tax_id: 'ABC101010111', + tax_system: '601', + address: { zip: '85900' }, + }, + items: [ + { + quantity: 1, + product: { + description: 'Ukelele', + product_key: '60131324', + price: 345.6, + taxes: [{ type: 'IVA', rate: 0.16 }], + }, + }, + ], + use: 'G01', + payment_form: PaymentForm.TARJETA_DE_DEBITO, +}) -const facturapi = new Facturapi(process.env.FACTURAPI_KEY!); +console.log({ id: invoice.id, status: invoice.status, total: invoice.total }) ``` -CommonJS: +Ejecuta `node primera-factura.mjs` con la variable de entorno configurada. Si todo salió bien, verás el ID, el estado y el total de tu primera factura. Guarda `invoice.id`: lo usaremos en los siguientes ejemplos. -```javascript -const Facturapi = require('facturapi').default; -``` +Para emitir en producción, configura los datos fiscales y el CSD de la organización y utiliza su Live Secret Key. Consulta la [guía de configuración de organizaciones](https://docs.facturapi.io/docs/getting-started/organization-onboarding). -### Create a customer +## ESM, CommonJS y TypeScript + +Elige la forma de importar que ya usas en tu proyecto. Con ESM o TypeScript: ```ts -const customer = await facturapi.customers.create({ - legal_name: 'Walter White', - tax_id: 'WIWA761018', - email: 'walterwhite@gmail.com', - address: { - zip: '06800', - country: 'MEX', - }, -}); +import Facturapi, { InvoiceType, type Invoice } from 'facturapi' ``` -### Create an invoice +Con CommonJS: -```ts -const invoice = await facturapi.invoices.create({ - customer: 'YOUR_CUSTOMER_ID', - payment_form: Facturapi.PaymentForm.TRANSFERENCIA_ELECTRONICA_DE_FONDOS, - items: [ - { - quantity: 1, - product: 'YOUR_PRODUCT_ID', - }, - ], -}); +```js +const Facturapi = require('facturapi') +const { InvoiceType, FacturapiError } = Facturapi ``` -#### Download your invoice +Los tipos y enums públicos se importan desde `facturapi`. El paquete incluye declaraciones para ESM y CommonJS; no necesitas instalar un paquete de tipos adicional para el SDK. -`downloadZip`, `downloadPdf` and `downloadXml` return a binary result: -- Node.js: stream-like object -- Browser: `Blob` +## Operaciones frecuentes -```ts -import fs from 'fs'; +Ya tienes una factura. Ahora puedes consultarla, descargarla o enviarla por correo. Estos ejemplos usan las variables `facturapi` e `invoice` que creaste arriba. Si usas CommonJS, coloca las llamadas con `await` dentro de una función `async`. + +### Consultar y buscar facturas -const file = await facturapi.invoices.downloadZip(invoice.id); +```js +const savedInvoice = await facturapi.invoices.retrieve(invoice.id) +const results = await facturapi.invoices.list({ + limit: 10, + date: { gte: new Date('2026-01-01T00:00:00Z') }, +}) -// Node-first style (explicit cast) -const stream = file as NodeJS.ReadableStream; -stream.pipe(fs.createWriteStream('/tmp/invoice.zip')); +console.log(savedInvoice.status, results.data) ``` -Portable style (Node + browser): +### Entregar el PDF o enviarlo por correo -```ts -const file = await facturapi.invoices.downloadZip(invoice.id); +```js +const download = await facturapi.invoices.downloadPdfUrl(invoice.id) +console.log(download.url, download.expires_at) + +await facturapi.invoices.sendByEmail(invoice.id, { + email: 'cliente@example.com', +}) +``` + +La URL de descarga es temporal y permite acceder al archivo a quien la tenga. Compártela solo con el destinatario correspondiente. También existen `downloadXmlUrl` y `downloadZipUrl`. + +Si necesitas recibir los archivos en tu aplicación, `downloadPdf`, `downloadXml` y `downloadZip` devuelven un stream en Node.js y un `Blob` en navegador. Por ejemplo, para guardar un ZIP en Node.js: + +```js +import { createWriteStream } from 'node:fs' + +const file = await facturapi.invoices.downloadZip(invoice.id) if ('pipe' in file && typeof file.pipe === 'function') { - file.pipe(fs.createWriteStream('/tmp/invoice.zip')); -} else { - const url = URL.createObjectURL(file); - window.open(url, '_blank'); + file.pipe(createWriteStream('factura.zip')) } ``` -If you would rather hand the file to someone else than receive it yourself, the -same representations are available as a short-lived URL. The URL is a bearer -credential for that one file and stops working when it expires: +### Manejar errores -```ts -const { url, filename } = await facturapi.invoices.downloadZipUrl(invoice.id); +```js +import { FacturapiError } from 'facturapi' + +try { + await facturapi.invoices.retrieve(invoice.id) +} catch (error) { + if (error instanceof FacturapiError) { + console.error(error.status, error.code, error.message) + console.error(error.errors) // Detalles de validación, cuando existen + } else { + throw error + } +} ``` -The URL variants follow the existing download methods: `downloadPdfUrl`, -`downloadXmlUrl`, and `downloadZipUrl`, where each format is available. ZIP -requests similarly provide `downloadZipRequestUrl` alongside -`downloadZipRequest`. +Usa `error.code` y los detalles de validación para decidir cómo responder; evita depender del texto del mensaje. Consulta la [referencia de errores](https://docs.facturapi.io/docs/getting-started/errors). -#### Send your invoice by email +### Crear clientes con tipos específicos + +Elige el método que corresponde a tu cliente para ver sus campos requeridos en el autocompletado: ```ts -await facturapi.invoices.sendByEmail(invoice.id, { - email: 'customer@example.com', -}); +await facturapi.customers.createNational({ + legal_name: 'EMPRESA DE EJEMPLO', + tax_id: 'ABC101010111', + tax_system: '601', + address: { zip: '83200' }, +}) +await facturapi.customers.createForeign({ + legal_name: 'Example Company', + address: { country: 'USA' }, +}) +await facturapi.customers.createGeneric({ + legal_name: 'PUBLICO EN GENERAL', + tax_id: 'XAXX010101000', +}) +``` + +Los tres métodos usan la misma operación de la API. `create()` sigue disponible si decides el caso dinámicamente, o si quieres guardar datos incompletos con `{ createEditLink: true }`. Las validaciones siguen siendo responsabilidad de la API. + +## Qué puedes integrar + +| Necesitas… | Recurso o guía | +| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| Emitir ingresos, egresos y complementos | `facturapi.invoices` · [Guías de facturas](https://docs.facturapi.io/docs/guides/invoices) | +| Reutilizar clientes y productos | `facturapi.customers` y `facturapi.products` | +| Ofrecer autofactura con recibos digitales | `facturapi.receipts` · [Guía de recibos](https://docs.facturapi.io/docs/guides/receipts) | +| Administrar emisores y certificados | `facturapi.organizations` · [Configuración](https://docs.facturapi.io/docs/getting-started/organization-onboarding) | +| Emitir retenciones | `facturapi.retentions` · [Guía de retenciones](https://docs.facturapi.io/docs/guides/invoices/retencion) | +| Consultar catálogos del SAT | `facturapi.catalogs`, `facturapi.cartaPorteCatalogs` y `facturapi.comercioExteriorCatalogs` | +| Recibir eventos y validar firmas | `facturapi.webhooks` · [Referencia de la API](https://docs.facturapi.io/api/) | + +## Compatibilidad + +| Entorno | Soporte | +| ------------ | ------------------------------------------------------------------------------- | +| Node.js | 18 o superior; CI ejecuta pruebas en Node 18 y 24 | +| Navegador | Requiere `fetch`, `FormData` y `Blob`; probado en Chromium | +| React Native | Requiere esas APIs globales; no se ejecuta una suite específica de React Native | + +Mantén las llaves secretas en tu servidor. La compatibilidad de runtime con navegadores no convierte una llave secreta en pública. + +## Actualizar desde v3, v4 o v5 + +Puedes pasar directamente a v6; no necesitas instalar las versiones intermedias. En Node.js, comprueba primero que uses la versión 18 o superior. Busca tu versión actual y revisa los apartados que le corresponden: + +| Tu versión | Qué revisar | +| ---------- | --------------------------------------------------------------- | +| 5.x | Fechas, imports y tipos de entrada | +| 4.x | Lo anterior y tipos de respuesta | +| 3.x | Los tres apartados, incluidos los métodos renombrados y Node.js | + +### ✅ Cuándo puedes actualizar sin cambiar tu código + +Si tu integración usa los métodos vigentes, importa desde `facturapi`, corre en Node.js 18+ y no depende de fechas como strings ni de los tipos anteriores que se describen abajo, puedes conservar tus llamadas al SDK. Por ejemplo, crear una factura, leer su `id` y descargar su PDF con los métodos actuales no requiere reescribir ese flujo. + +También puedes conservar: + +- **Tus imports públicos:** `import Facturapi from 'facturapi'` y el `require('facturapi')` de v3 funcionan en v6. Si usabas `.default` en v4/v5, ese alias sigue disponible. +- **La inicialización y los enums:** `new Facturapi(apiKey)` y accesos como `Facturapi.PaymentForm.EFECTIVO` siguen funcionando. No necesitas cambiar tus llaves por actualizar el SDK. +- **Las descargas en Node.js:** los métodos `downloadPdf`, `downloadXml` y `downloadZip` siguen devolviendo streams que puedes guardar con `.pipe()`. +- **El manejo básico de errores:** puedes seguir usando `catch` y `error.message`. Los campos de `FacturapiError` son información adicional que puedes adoptar cuando la necesites. + +Actualiza la dependencia con `npm install facturapi@^6` (o el equivalente de tu gestor) y ejecuta las pruebas de tu integración. Si usas TypeScript, comprueba también la compilación: sus tipos ahora describen más casos reales de la respuesta. + +### Desde v5: fechas, imports y tipos de entrada + +**Fechas de respuesta.** Los campos de fecha como `created_at`, `date` y `expires_at` ahora son objetos `Date` en ejecución, incluso donde versiones anteriores ya los declaraban como `Date` en TypeScript. Esto también aplica al evento que devuelve `webhooks.validateSignature`. + +Si usabas métodos de string como `.slice()` o `.split()`, convierte primero la fecha. Comprueba `null` cuando el campo lo permita: + +```js +const invoiceDate = invoice.date?.toISOString() ?? null ``` -## Documentation +Si ya usabas métodos de `Date`, o no leías esos campos, no necesitas adaptarlos. `JSON.stringify()` convierte los objetos `Date` a strings ISO automáticamente, aunque su formato puede normalizarse (por ejemplo, incluir milisegundos); no dependas de conservar el texto exacto de la respuesta anterior. + +`stamp.date` conserva el string de fecha y hora del SAT. Las fechas de calendario declaradas como `date` en la API también conservan su texto, por ejemplo las fechas de nómina en formato `YYYY-MM-DD`. El SDK tampoco convierte los valores de `metadata`. Los filtros de entrada, como `date: { gte, lt }`, siguen siendo objetos de rango; no necesitas convertirlos en una sola fecha. + +**Valores ausentes.** Los tipos ahora permiten `null` donde la API puede devolverlo: por ejemplo, en `invoice.date`, `retention.fecha_exp` y `organization.pending_plan_update`. Conserva tus comprobaciones si ya contemplabas ese caso; de lo contrario, agrégalas antes de acceder al valor. Revisa también tus fixtures de TypeScript. + +**Imports.** Si importas desde `facturapi`, puedes seguir haciéndolo. Si importabas desde `facturapi/dist/...` u otra ruta interna, usa la raíz del paquete: los tipos, enums y el constructor públicos están disponibles allí. + +**TypeScript.** Las entradas ahora describen los campos que acepta la API. Si tus objetos ya cumplen ese contrato, no necesitas cambiar las llamadas. Corrige los campos desconocidos o de otro tipo que antes pasaban por `Record`; las fechas de entrada siguen aceptando strings ISO y objetos `Date`. Los tipos de respuesta también reflejan campos opcionales: por ejemplo, `property_tax_account` puede faltar y las fechas de un rol pueden ser `null`. -Visit [docs.facturapi.io](https://docs.facturapi.io). +Los tipos de CFDI distinguen emisión, borrador y edición; cada complemento relaciona su `type` con la estructura de `data`. En nómina, las entradas usan las claves del catálogo de percepciones publicado: `019` requiere `horas_extra`, y el origen de recursos `IM` requiere `monto_recurso_propio`. Si incluyes autotransporte de Carta Porte, completa su vehículo y seguro de responsabilidad civil. Estas relaciones ayudan a detectar errores al compilar; la API sigue siendo responsable de validar los datos. -## Help +**Clientes.** No necesitas reemplazar `customers.create()`: los métodos `createNational()`, `createForeign()` y `createGeneric()` son opcionales. Para crear datos incompletos, usa `customers.create(data, { createEditLink: true })`. El flag debe ser literalmente `true` para que TypeScript seleccione esa entrada; un boolean dinámico conserva los campos del contrato normal. Los métodos específicos conservan sus campos requeridos aunque envíes ese flag. -### Found a bug? +**Cancelaciones.** Cuando uses los motivos `01` o `04`, incluye `substitution`. Los motivos `02` y `03` no lo requieren. Para eliminar un borrador, puedes seguir llamando a `cancel(id)` sin parámetros. -Please report it on the issue tracker. +**Recibos.** `receipts.toInvoice(data)` distingue la factura creada del resumen devuelto con `dry_run: true`. Si el flag es dinámico, comprueba qué respuesta recibiste antes de acceder a campos exclusivos de una factura. En `createGlobalInvoice()`, si proporcionas `receipts`, incluye `from` y `to`; si tu petición ya los incluía, no necesitas cambiarla. -### Want to contribute? +Si consultabas `invoice.cancellation`, usa `invoice.cancellation_status` para el estado y `invoice.canceled_at` para la fecha de cancelación. En solicitudes de ZIP, utiliza las fechas documentadas como `created_at` y `scheduled_at`; `updated_at` no forma parte de esa respuesta. -Send us your PR! We appreciate your help :) +### Desde v4: tipos de respuesta + +Además de lo anterior, revisa el código que depende de la forma de las respuestas: + +- En `SearchResult`, `page`, `total_pages` y `total_results` pueden faltar. Comprueba que existan antes de hacer cálculos; un total ausente no significa cero. Si solo recorres `result.data`, no necesitas cambiar ese código. +- Si importabas `CursorSearchResult`, usa `SearchResult`. Los campos `previous_cursor` y `next_cursor` son opcionales. +- Si vienes de una versión anterior a 4.20, `property_tax_account` se declara como un arreglo de strings. Si tus datos ya reflejan la respuesta de la API, no necesitas transformarlos. + +### Desde v3: métodos renombrados y Node.js + +Revisa también los dos apartados anteriores. Necesitas **Node.js 18 o superior**; si ya lo usas, no tienes que cambiar de runtime para instalar v6. + +Estos son los reemplazos de los métodos retirados en v4. Solo necesitas cambiar las llamadas que uses: + +| Antes | En v6 | +| ---------------------------------------- | -------------------------------------------------- | +| `facturapi.products.keys('café')` | `facturapi.catalogs.searchProducts({ q: 'café' })` | +| `facturapi.products.units('pieza')` | `facturapi.catalogs.searchUnits({ q: 'pieza' })` | +| `facturapi.invoices.editDraft(id, data)` | `facturapi.invoices.updateDraft(id, data)` | + +Si sigues en **3.0 o 3.1** y usabas `organizations.getApiKeys`, ese método se retiró en 3.2. Para consultar la llave de prueba, usa `organizations.getTestApiKey(id)`. Para producción, conserva tu llave existente; `listLiveApiKeys(id)` devuelve información de las llaves, no sus secretos completos. Los métodos `renewTestApiKey` y `renewLiveApiKey` rotan credenciales: no los uses como sustituto de una consulta. + +Si usas TypeScript, el SDK ya incluye sus propios tipos. Revisa tus declaraciones locales y fixtures: las respuestas antes sin tipar ahora incluyen enums, campos opcionales y valores nullable. Una integración en JavaScript no necesita convertirse a TypeScript. + +Para ver las novedades de cada versión, consulta el [changelog](CHANGELOG.md). + +## Ayuda y contribuciones + +¿Encontraste un problema? [Abre un issue](https://github.com/FacturAPI/facturapi-node/issues/new) con la versión del SDK, tu runtime y un ejemplo mínimo reproducible. Omite llaves secretas y datos fiscales reales. + +Para dudas de integración, consulta la [documentación](https://docs.facturapi.io) o escribe a [contacto@facturapi.io](mailto:contacto@facturapi.io). + +Para contribuir, instala las dependencias con la versión de pnpm indicada en `package.json` y Node.js 24.11 o superior compatible con las herramientas de build: + +```sh +pnpm install +pnpm test +pnpm run lint +``` + +### Explora los tipos y el autocompletado + +Abre [`playground/index.mts`](playground/index.mts) en VSCode y pasa el cursor sobre los métodos y respuestas, o modifica las entradas para probar el autocompletado. El archivo importa el paquete desde el build local, con los mismos exports y declaraciones que se publican en npm. Sus funciones no se ejecutan automáticamente ni hacen llamadas al abrir el archivo. + +```sh +pnpm playground:check +``` -### Contact us! +El comando actualiza el build y comprueba los ejemplos. Vuelve a ejecutarlo después de cambiar el SDK; las comprobaciones normales de tipos también incluyen el playground. -contacto@facturapi.io +El proyecto se distribuye bajo la [licencia MIT](LICENSE). diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 79c6a25..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,33 +0,0 @@ -const js = require('@eslint/js') -const tseslint = require('typescript-eslint') -const globals = require('globals') -const eslintConfigPrettier = require('eslint-config-prettier') - -module.exports = [ - { - ignores: ['dist/**', 'node_modules/**', 'coverage/**'], - }, - js.configs.recommended, - ...tseslint.configs.recommended, - { - files: ['**/*.{js,cjs,mjs,ts}'], - languageOptions: { - globals: { - ...globals.node, - ...globals.browser, - }, - }, - rules: { - semi: ['error', 'never'], - quotes: ['error', 'single', { avoidEscape: true }], - curly: ['error', 'multi-line'], - 'space-before-function-paren': ['error', 'always'], - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-require-imports': 'off', - '@typescript-eslint/no-duplicate-enum-values': 'off', - 'no-useless-assignment': 'off', - }, - }, - eslintConfigPrettier, -] diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..812e3be --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import { defineConfig, globalIgnores } from 'eslint/config' +import tseslint from 'typescript-eslint' +import globals from 'globals' +import eslintConfigPrettier from 'eslint-config-prettier/flat' + +export default defineConfig([ + globalIgnores(['dist/**', 'node_modules/**', 'coverage/**', 'test-results/**']), + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.{js,cjs,mjs,ts,cts,mts}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.browser, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-duplicate-enum-values': 'off', + 'no-useless-assignment': 'off', + }, + }, + eslintConfigPrettier, +]) diff --git a/openapi/source.json b/openapi/source.json new file mode 100644 index 0000000..3aa7568 --- /dev/null +++ b/openapi/source.json @@ -0,0 +1,5 @@ +{ + "repository": "FacturAPI/facturapi-docs", + "revision": "fa739524c4d72c4aae9a1253188f166c228a9db0", + "path": "website/openapi_v2.yaml" +} diff --git a/package.json b/package.json index effcd8b..68de320 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "facturapi", - "version": "5.1.0", + "version": "6.0.0", "description": "SDK oficial de Facturapi para Node.js y navegadores. Integra facturaci\u00f3n electr\u00f3nica en M\u00e9xico (CFDI) de forma simple y obt\u00e9n una perspectiva fiscal completa de tu operaci\u00f3n, con b\u00fasquedas indexadas, env\u00edo de documentos y trazabilidad.", - "main": "dist/index.cjs.js", - "module": "dist/index.es.js", - "types": "dist/index.d.ts", + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "types": "dist/index.d.cts", "sideEffects": false, "files": [ "dist", @@ -16,25 +16,29 @@ "access": "public", "provenance": true }, - "packageManager": "pnpm@11.9.0", + "packageManager": "pnpm@12.6.0", "scripts": { - "precommit": "lint-staged", - "build": "vite build && tsc --emitDeclarationOnly", + "build": "vite build && tsc --noEmit && rolldown -c && node scripts/commonjs-types.mjs", "lint": "eslint .", "lint:fix": "eslint . --fix", "format": "prettier . --write", "format:check": "prettier . --check", - "test:node": "vitest run --config vitest.node.config.ts", - "test:web": "vitest run --config vitest.web.config.ts", + "test:node": "vitest run --config vitest.node.config.mts", + "test:web": "vitest run --config vitest.web.config.mts", "test:browser": "pnpm run build && playwright test", "test:unit": "pnpm run test:node && pnpm run test:web", - "test:types": "tsd", - "test": "pnpm run build && pnpm run test:unit && pnpm run test:types", - "ci": "pnpm run test" + "test:types": "tsd --files test-d/runtime-types.test-d.ts && tsc --ignoreConfig --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 test-d/package-exports.mts test-d/package-exports.cts && tsc --ignoreConfig --noEmit --module commonjs --moduleResolution node10 --ignoreDeprecations 6.0 --target ES2022 test-d/legacy-package-exports.cts && tsc --project playground", + "test": "pnpm run build && pnpm run test:unit && pnpm run test:types && pnpm run test:compat", + "ci": "pnpm run test", + "test:compat": "node --test test/compat/*.test.cjs test/compat/*.test.mjs", + "generate:sdk": "node scripts/generate-sdk.mjs", + "generate:sdk:check": "node scripts/generate-sdk.mjs --check", + "sync:openapi": "node scripts/sync-openapi.mjs", + "playground:check": "pnpm run build && tsc --project playground" }, "engines": { "node": ">=18.0.0", - "pnpm": ">=11.9.0" + "pnpm": ">=12.6.0" }, "repository": { "type": "git", @@ -66,33 +70,37 @@ "url": "https://github.com/facturapi/facturapi-node/issues" }, "homepage": "https://github.com/facturapi/facturapi-node#readme", - "lint-staged": { - "*.{js,cjs,mjs,ts}": [ - "prettier --write", - "eslint --fix" - ], - "*.{json,md,yml,yaml,css}": [ - "prettier --write" - ] - }, "devDependencies": { "@eslint/js": "^10.0.1", - "@playwright/test": "1.61.0", - "@rollup/plugin-commonjs": "^29.0.3", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-replace": "^6.0.3", - "@types/node": "^26.0.0", - "eslint": "^10.5.0", + "@playwright/test": "1.63.0", + "@types/node": "^26.6.3", + "eslint": "^10.11.0", "eslint-config-prettier": "^10.1.8", - "globals": "^17.7.0", - "husky": "^9.1.7", - "jsdom": "^29.1.1", - "lint-staged": "^17.0.8", - "prettier": "^3.8.4", + "globals": "^17.12.0", + "js-yaml": "5.4.2", + "jsdom": "^30.1.1", + "openapi-typescript": "7.13.0", + "prettier": "^3.9.9", + "rolldown": "^1.2.11", + "rolldown-plugin-dts": "^0.28.6", "tsd": "^0.33.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.62.0", - "vite": "8.0.16", - "vitest": "^4.1.9" + "typescript-eslint": "^8.70.1", + "vite": "8.3.1", + "vitest": "^5.0.2" + }, + "exports": { + ".": { + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + }, + "default": "./dist/index.mjs" + }, + "./package.json": "./package.json" } } diff --git a/playground/index.mts b/playground/index.mts new file mode 100644 index 0000000..6b2fede --- /dev/null +++ b/playground/index.mts @@ -0,0 +1,90 @@ +import Facturapi, { PaymentForm, type InvoiceCreateInput } from 'facturapi' + +const facturapi = new Facturapi('sk_test_solo_editor') + +export const ingreso = { + customer: 'cus_ejemplo', + payment_form: PaymentForm.TARJETA_DE_DEBITO, + items: [ + { + quantity: 1, + product: { description: 'Ejemplo', product_key: '60131324', price: 100 }, + }, + ], +} satisfies InvoiceCreateInput + +export const pago = { + type: 'P', + customer: 'cus_ejemplo', + complements: [ + { + type: 'pago', + data: { + payment_form: '28', + related_documents: [ + { + uuid: '39c85a3f-275b-4341-b259-e8971d9f8a94', + amount: 100, + installment: 1, + last_balance: 100, + taxes: [], + }, + ], + }, + }, + ], +} satisfies InvoiceCreateInput + +// Estas funciones sirven para explorar IntelliSense; no se llaman al abrir el archivo. +export async function explorarRespuestas() { + const factura = await facturapi.invoices.create(ingreso) + const resultados = await facturapi.invoices.list({ + pagination: 'cursor', + limit: 10, + }) + return { + fecha: factura.date?.toISOString(), + fechaTimbrado: factura.stamp?.date, + facturas: resultados.data, + } +} + +export async function explorarDryRun() { + const resumen = await facturapi.receipts.toInvoice({ + keys: ['rec_ejemplo'], + dry_run: true, + }) + const factura = await facturapi.receipts.toInvoice({ keys: ['rec_ejemplo'] }) + return { resumen, factura } +} + +export function explorarDescargas() { + return facturapi.invoices.downloadPdf('inv_ejemplo') +} + +// Explora los tipos de respuesta o cambia los campos de entrada. +export async function explorarUrls() { + const download = await facturapi.invoices.downloadPdfUrl('inv_ejemplo') + return { + url: download.url, + expiresAt: download.expires_at.toISOString(), + filename: download.filename, + contentType: download.content_type, + } +} + +export async function explorarResumenDePago() { + const summary = await facturapi.invoices.paymentSummary('inv_ejemplo', { + amount: 100, + }) + return facturapi.invoices.create({ + type: 'P', + customer: 'cus_ejemplo', + complements: [ + { + type: 'pago', + data: { payment_form: '28', related_documents: [summary] }, + }, + ], + }) +} diff --git a/playground/tsconfig.json b/playground/tsconfig.json new file mode 100644 index 0000000..60a9eed --- /dev/null +++ b/playground/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ES2022", + "strict": true, + "noEmit": true + }, + "include": ["index.mts"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ee7ef3..3b2d5b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3 +1,186 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + '@pnpm/exe': + specifier: 12.6.0 + version: 12.6.0 + pnpm: + specifier: 12.6.0 + version: 12.6.0 + +packages: + + '@pnpm/exe.android-arm64@12.6.0': + resolution: {integrity: sha512-kviIHft9h02q+7N2In7tSL9T/HRUSGwYmU74YPtsWU5ee7vgqPyC0JT6RRX6miW+NxX1CvHgQxg69qq1qTLJYQ==} + cpu: [arm64] + os: [android] + + '@pnpm/exe.android-x64@12.6.0': + resolution: {integrity: sha512-CT8aJKLq2mtZFE71pr4E5Z2xHL8uGnRGr+NclDqsXlVF4SVcQ2QAs14mWi0C8gjT4hbmi+Q0lJRRIkMAWfjjng==} + cpu: [x64] + os: [android] + + '@pnpm/exe.darwin-arm64@12.6.0': + resolution: {integrity: sha512-rafpVkjzugKBMxSvGQd5wK1x5eOTkD/+lcJIFHeQhvd+BJ8kDisOOvwhQDrpGd4vd2Fx+hhW0P2Ptt638OlhFg==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.6.0': + resolution: {integrity: sha512-72Jpuv1m24gI8zUNcaylYpBWEhBzz1VPhnDIU2GYM2eRP+KsOqVLwV78i+JrihI39zY2NNXmaN4eAKX1inpaDQ==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.freebsd-x64@12.6.0': + resolution: {integrity: sha512-LON4QgNy1w/XF4uySZIyC/5hEB0oGdelXsY9tSKqstER+2j2X2oHz67skD11RRd/HWFRtMr64shQZ4I9ZoZ0zg==} + cpu: [x64] + os: [freebsd] + + '@pnpm/exe.linux-arm64-musl@12.6.0': + resolution: {integrity: sha512-BdDpX+DeaMUc5x6WNcE6FkmFy36NwrBbBvwsZU737Zt3u1fTY+iKFPchjEQNCM4rT6q6xvF2oN3ZwExGsJCkxQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.6.0': + resolution: {integrity: sha512-8h2sNoIhHDpHDYqZZCh9PXr6krqW10btb0GHVGuw710muDHlFAHMtUG2ogmaHge6zJG1xgY4Y7mwX5g/LWvrYg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-ppc64@12.6.0': + resolution: {integrity: sha512-ld6xgcEhFCFrsVsJhbmdmR714PnsEspO/Ij8w0/D7OSiz2hYGu3fZd5tKRxOI5m6H6Gl0/RRFAPncTHbsgXVjQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-riscv64@12.6.0': + resolution: {integrity: sha512-HIbImydoC3J8NFt+8MXfhTCf5rO6NjCMyinSAHac0VmV8uCHw+kbQkyAzxV84rzz9ZOzmBOnj0b1N461UIYGsw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-s390x@12.6.0': + resolution: {integrity: sha512-DjSqT7+BZ/lWcDHwNMuzsRVfyxUimh+D54Xw4tSWbdVVQhtWtNMUyI93LVnwCmsoEpar2gC3SFeAgywx37svKQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.6.0': + resolution: {integrity: sha512-31lKeGPmRE6xfV6I3VjaEGVFRei14pl/zgoFDK4w+UkbJqOuNl2Ht3O1GuqNIg3Gl14qTEb4kZRAYFHXifDx9A==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.6.0': + resolution: {integrity: sha512-qFWBneHJAJ73W4whtbaFOL1M/7DBC6ILHXuxc7ZPtEhfPuT1zeZiGrmKHoMAfJA+mcm6xhOFljqVTUS+00Jabw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.6.0': + resolution: {integrity: sha512-OhfefXEEykZlslSUhR8PPRe6MVPV3Oink/dVfIecE5velpc7j80cZYsHlaDrtRDcm3TPwQHkaRW1SJ1efX9oFg==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.6.0': + resolution: {integrity: sha512-L2tuyrD2+Imgxs3VK/ST/2L3xD6vDP0ktJQxM0TaGw7TbAQEMq+RMc8iK6Ew7Id579uzjJe8jSfJID2ZGsOHCA==} + cpu: [x64] + os: [win32] + + '@pnpm/exe@12.6.0': + resolution: {integrity: sha512-CkNetlJZugjKp9vPvWqCm5ahORU6FfO46BlOqqSCKLJ+W6QcRgM0qmmPTvlgrXVvkAiH+9hE+mMp/wSaqcU5Aw==} + engines: {node: '>=18.*'} + hasBin: true + + pnpm@12.6.0: + resolution: {integrity: sha512-PvaPlRyxEawgS0paFvCy3fDaVqluBBPoHYVdnwtV75JnFHCQKOHNAMQFwsX7e56OxNxGd3yAXQNzwvL/AP0g7A==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.android-arm64@12.6.0': + optional: true + + '@pnpm/exe.android-x64@12.6.0': + optional: true + + '@pnpm/exe.darwin-arm64@12.6.0': + optional: true + + '@pnpm/exe.darwin-x64@12.6.0': + optional: true + + '@pnpm/exe.freebsd-x64@12.6.0': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.6.0': + optional: true + + '@pnpm/exe.linux-arm64@12.6.0': + optional: true + + '@pnpm/exe.linux-ppc64@12.6.0': + optional: true + + '@pnpm/exe.linux-riscv64@12.6.0': + optional: true + + '@pnpm/exe.linux-s390x@12.6.0': + optional: true + + '@pnpm/exe.linux-x64-musl@12.6.0': + optional: true + + '@pnpm/exe.linux-x64@12.6.0': + optional: true + + '@pnpm/exe.win32-arm64@12.6.0': + optional: true + + '@pnpm/exe.win32-x64@12.6.0': + optional: true + + '@pnpm/exe@12.6.0': + optionalDependencies: + '@pnpm/exe.android-arm64': 12.6.0 + '@pnpm/exe.android-x64': 12.6.0 + '@pnpm/exe.darwin-arm64': 12.6.0 + '@pnpm/exe.darwin-x64': 12.6.0 + '@pnpm/exe.freebsd-x64': 12.6.0 + '@pnpm/exe.linux-arm64': 12.6.0 + '@pnpm/exe.linux-arm64-musl': 12.6.0 + '@pnpm/exe.linux-ppc64': 12.6.0 + '@pnpm/exe.linux-riscv64': 12.6.0 + '@pnpm/exe.linux-s390x': 12.6.0 + '@pnpm/exe.linux-x64': 12.6.0 + '@pnpm/exe.linux-x64-musl': 12.6.0 + '@pnpm/exe.win32-arm64': 12.6.0 + '@pnpm/exe.win32-x64': 12.6.0 + + pnpm@12.6.0: + optionalDependencies: + '@pnpm/exe.android-arm64': 12.6.0 + '@pnpm/exe.android-x64': 12.6.0 + '@pnpm/exe.darwin-arm64': 12.6.0 + '@pnpm/exe.darwin-x64': 12.6.0 + '@pnpm/exe.freebsd-x64': 12.6.0 + '@pnpm/exe.linux-arm64': 12.6.0 + '@pnpm/exe.linux-arm64-musl': 12.6.0 + '@pnpm/exe.linux-ppc64': 12.6.0 + '@pnpm/exe.linux-riscv64': 12.6.0 + '@pnpm/exe.linux-s390x': 12.6.0 + '@pnpm/exe.linux-x64': 12.6.0 + '@pnpm/exe.linux-x64-musl': 12.6.0 + '@pnpm/exe.win32-arm64': 12.6.0 + '@pnpm/exe.win32-x64': 12.6.0 + +--- lockfileVersion: '9.0' settings: @@ -10,43 +193,40 @@ importers: devDependencies: '@eslint/js': specifier: ^10.0.1 - version: 10.0.1(eslint@10.5.0) + version: 10.0.1(eslint@10.11.0(supports-color@10.2.2)) '@playwright/test': - specifier: 1.61.0 - version: 1.61.0 - '@rollup/plugin-commonjs': - specifier: ^29.0.3 - version: 29.0.3 - '@rollup/plugin-node-resolve': - specifier: ^16.0.3 - version: 16.0.3 - '@rollup/plugin-replace': - specifier: ^6.0.3 - version: 6.0.3 + specifier: 1.63.0 + version: 1.63.0 '@types/node': - specifier: ^26.0.0 - version: 26.0.0 + specifier: ^26.6.3 + version: 26.6.3 eslint: - specifier: ^10.5.0 - version: 10.5.0 + specifier: ^10.11.0 + version: 10.11.0(supports-color@10.2.2) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@10.5.0) + version: 10.1.8(eslint@10.11.0(supports-color@10.2.2)) globals: - specifier: ^17.7.0 - version: 17.7.0 - husky: - specifier: ^9.1.7 - version: 9.1.7 + specifier: ^17.12.0 + version: 17.12.0 + js-yaml: + specifier: 5.4.2 + version: 5.4.2 jsdom: - specifier: ^29.1.1 - version: 29.1.1 - lint-staged: - specifier: ^17.0.8 - version: 17.0.8 + specifier: ^30.1.1 + version: 30.1.1 + openapi-typescript: + specifier: 7.13.0 + version: 7.13.0(typescript@6.0.3) prettier: - specifier: ^3.8.4 - version: 3.8.4 + specifier: ^3.9.9 + version: 3.9.9 + rolldown: + specifier: ^1.2.11 + version: 1.2.11 + rolldown-plugin-dts: + specifier: ^0.28.6 + version: 0.28.6(rolldown@1.2.11)(typescript@6.0.3) tsd: specifier: ^0.33.0 version: 0.33.0 @@ -54,31 +234,24 @@ importers: specifier: ^6.0.3 version: 6.0.3 typescript-eslint: - specifier: ^8.62.0 - version: 8.62.0(eslint@10.5.0)(typescript@6.0.3) + specifier: ^8.70.1 + version: 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) vite: - specifier: 8.0.16 - version: 8.0.16(@types/node@26.0.0)(yaml@2.9.0) + specifier: 8.3.1 + version: 8.3.1(@types/node@26.6.3)(yaml@2.9.1) vitest: - specifier: ^4.1.9 - version: 4.1.11(@types/node@26.0.0)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.0.0)(yaml@2.9.0)) + specifier: ^5.0.2 + version: 5.0.2(@types/node@26.6.3)(jsdom@30.1.1)(vite@8.3.1(@types/node@26.6.3)(yaml@2.9.1)) packages: - '@asamuzakjp/css-color@5.1.11': - resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/dom-selector@7.1.1': - resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/generational-cache@1.0.1': - resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@asamuzakjp/css-color@7.1.2': + resolution: {integrity: sha512-99DHAnXDB5z6EEK+9GMpVI7Mw4oxj97dY5bpOzMnjADQWxI8rN6TvTduuFLUhUMlS7/CfVZ06tcZsus6cltnNw==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@asamuzakjp/dom-selector@9.2.2': + resolution: {integrity: sha512-lSWTBMjAcmu2xn5yEDU7jh6QDV+C8GEKtdJ4pIQhXh26RkKQ7S3FuQlt+zZkUbTdJ4d3XyV1kPI/G0zWXxqaqw==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} @@ -92,53 +265,50 @@ packages: resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true - '@csstools/color-helpers@6.0.2': - resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + '@cacheable/memory@2.2.0': + resolution: {integrity: sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==} + + '@cacheable/utils@2.5.0': + resolution: {integrity: sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==} + + '@csstools/color-helpers@6.1.2': + resolution: {integrity: sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==} engines: {node: '>=20.19.0'} - '@csstools/css-calc@3.2.1': - resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + '@csstools/css-calc@3.4.1': + resolution: {integrity: sha512-EtC7SoN1j6J4E4DCwg5QgbO5TGxgxIA1RXqe+W+qUM+BUcezx9wT+/tiQ/WO2yCX4i5X+Cuf9ciJ22aP4UEwWw==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^4.0.1 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-color-parser@4.1.8': - resolution: {integrity: sha512-3chWb7PRLijpJpPIKkDxdu6IBeO5MrFACND57On0j8OPpc0wZibcGc3xAHrSEbOx/KDRyMHoIxGn0w1PhXMYHw==} + '@csstools/css-color-parser@4.2.4': + resolution: {integrity: sha512-DyefytAZ735mX4Dq/WcDAXFtXhaEFvme0ZS9tVEBAc2whxUthXr0R0L2rmEPm59SrMBkGrFzQviBXMs/UtnABQ==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^4.0.1 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-parser-algorithms@4.0.0': - resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + '@csstools/css-parser-algorithms@4.0.1': + resolution: {integrity: sha512-ShL8BqPfbKJrJiKFH0xBbN0i7Nrh9HXYRuF+pzyj93R/BL2YAsUxJeqANErzqM+0JGl7vjHp+3OIgd/DL69YIA==} engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.2 - '@csstools/css-syntax-patches-for-csstree@1.1.5': - resolution: {integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==} + '@csstools/css-syntax-patches-for-csstree@1.1.14': + resolution: {integrity: sha512-HpbVXyrofRXpHpgkNIjU/3EWR4WJvOkO3emNK/L6X/mTJU7bGUI3AkkpoTNXznQLp0KRjLHELTGeKI5dIkI9JQ==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: css-tree: optional: true - '@csstools/css-tokenizer@4.0.0': - resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + '@csstools/css-tokenizer@4.0.2': + resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==} engines: {node: '>=20.19.0'} - '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - - '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - - '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -151,8 +321,8 @@ packages: resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.6.0': - resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.2.1': @@ -172,12 +342,12 @@ packages: resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.2': - resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + '@eslint/plugin-kit@0.7.3': + resolution: {integrity: sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@exodus/bytes@1.15.1': - resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + '@exodus/bytes@1.16.0': + resolution: {integrity: sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: '@noble/hashes': ^1.8.0 || ^2.0.0 @@ -209,14 +379,24 @@ packages: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} - '@napi-rs/wasm-runtime@1.1.5': - resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} + engines: {node: '>= 18'} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + keyv: ^5.6.0 + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -230,105 +410,116 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/types@0.133.0': - resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxc-project/types@0.151.0': + resolution: {integrity: sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==} - '@playwright/test@1.61.0': - resolution: {integrity: sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==} - engines: {node: '>=18'} + '@playwright/test@1.63.0': + resolution: {integrity: sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==} + engines: {node: '>=20'} hasBin: true - '@rolldown/binding-android-arm64@1.0.3': - resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + '@redocly/ajv@8.11.2': + resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==} + + '@redocly/config@0.22.0': + resolution: {integrity: sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==} + + '@redocly/openapi-core@1.34.20': + resolution: {integrity: sha512-ypeBZ/6BKXR9+7/TtbKhbl4UgD7raHhPS12oknlKno2A8+lnFkxIwiE/Aklu6L2cd/ioH+fCWuMxi9/p3EyAPw==} + engines: {node: '>=18.17.0', npm: '>=9.5.0'} + + '@rolldown/binding-android-arm-eabi@1.2.11': + resolution: {integrity: sha512-A5kXfGKvKWWZE0TtPrfsvT+q4Y5d1QG8gGUzpYjGydM+fARM9MuX90PrXYXe0XbsDVgyxxNzHo6giCj90bsFNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.11': + resolution: {integrity: sha512-z6cTycz+iJ4PVkuL4HHW4DfTfoeU/2nqYYuSOrTmH7yHK5Y0LCOnA03V4ZNxavyVaU1oOqUgIg2klN/s+USGOA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.3': - resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + '@rolldown/binding-darwin-arm64@1.2.11': + resolution: {integrity: sha512-jShvqNtP6vDC6/A5JOAzbVV+DkgHqhl/ScVCJEbt+TUY6QYz7YnXcrg3sLtFBniro0f/Ld50ZwCWA6f7KYD1nQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.3': - resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + '@rolldown/binding-darwin-x64@1.2.11': + resolution: {integrity: sha512-f2i2xiNWq1Z1l2++q2fuhZRdLAT3aqxD6vRNm1RAxpUoBcdqNB3C0s1Bt+K+PbEx2F5F4gQp6hqKkphCY/xF9w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.3': - resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + '@rolldown/binding-freebsd-x64@1.2.11': + resolution: {integrity: sha512-4Ir5FSOKIAMr4r0kExpt1s3bMgzJU3rA45AYOHtQpls0oNeqcYBKrWMlckrYH4KCfGLfkfn1tN1dmZPMVsdXow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': - resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.11': + resolution: {integrity: sha512-/gnRDM+39BROzAN/k1OZjDPnDMcZxB/0EUxKjONO5yVkNEvlsoMDrxGNKgZi/ttFriS2gwlDNzB65pvNbFOXIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.3': - resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + '@rolldown/binding-linux-arm64-gnu@1.2.11': + resolution: {integrity: sha512-PFaK8HwvAHbaKbBcDNQihjMKYvFnA5hiENx/l5tphTDz1E0WFp32l0A7aq7lyUwGsRw/xSrNIy/gIK4thrSCrw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.3': - resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + '@rolldown/binding-linux-arm64-musl@1.2.11': + resolution: {integrity: sha512-AskzJUIKRLPxkruR1wLKewGbOw+EYfU/9lOrBFj4AFrEA8hPpKFnODWNu2WLaNs0QNkEb9QIJufmVZZIL/bJlg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.3': - resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + '@rolldown/binding-linux-ppc64-gnu@1.2.11': + resolution: {integrity: sha512-qlUGAheh2yh8afH7QBgx0PrRHN85hKnNd78x8MeMhXivuevgd8vgf6/CstOzmNKY/lLTHvNTrPy98cLnAugzJw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.3': - resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + '@rolldown/binding-linux-s390x-gnu@1.2.11': + resolution: {integrity: sha512-secpEad+0vCbSfn8upFySkDskv+bGPk3THSDS9Y89yc4rb4kzqHp8Dmyd9BkQW4SnhNXBZCl/6CrO//hZahNJQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.3': - resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + '@rolldown/binding-linux-x64-gnu@1.2.11': + resolution: {integrity: sha512-mOVBT3dPpkWm8XBWPmU4bf+U6dYDLeMo/9ojUmis4N0L5uu10qra5vOyngZ7/PSdoE4G9KvRt4bloRxNjLas7A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.3': - resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + '@rolldown/binding-linux-x64-musl@1.2.11': + resolution: {integrity: sha512-Is78i9A8Ui4SqcxUwFJ9uMmjDn58IbVTjFWYdQestFEgeuEmHMLGNriXnVJKkwG2YiZjw8cP0zCTyDMdDGtOOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.3': - resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + '@rolldown/binding-openharmony-arm64@1.2.11': + resolution: {integrity: sha512-dUCXneZ87INUMyQ0D+C0HrEBNUPNXHaPmU5GTjyKTJEiussw9Kaj5Ln8UztPe4epV/ffvgNBEadksdYhmW6xJA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.3': - resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.0.3': - resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + '@rolldown/binding-win32-arm64-msvc@1.2.11': + resolution: {integrity: sha512-jByxb6qfd+bH1xUd0qnfFnb17i9sWBPY2tOavJ0l3tdr3OTu+Kvtm8cd/JV5nFt657b1VqGltxg9olOEfofXWw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.3': - resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + '@rolldown/binding-win32-x64-msvc@1.2.11': + resolution: {integrity: sha512-/PzKqzAJ03i19oy2ItPvyvaVjOjBCNnfaJs8yvUdGBKmiESgnrJSQ2awd81QzFbbnAmu7YO9ZnJrDCb9VSJPRA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -336,55 +527,13 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rollup/plugin-commonjs@29.0.3': - resolution: {integrity: sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==} - engines: {node: '>=16.0.0 || 14 >= 14.17'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@16.0.3': - resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@6.0.3': - resolution: {integrity: sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@5.4.0': - resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@sinclair/typebox@0.27.10': - resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@sinclair/typebox@0.27.12': + resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} '@tsd/typescript@5.9.3': resolution: {integrity: sha512-JSSdNiS0wgd8GHhBwnMAI18Y8XPhLVN+dNelPfZCXFhy9Lb3NbnFyp9JKxxr54jSUkEJPk3cidvCoHducSaRMQ==} engines: {node: '>=14.17'} - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} - '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -406,79 +555,73 @@ packages: '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/node@26.0.0': - resolution: {integrity: sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==} + '@types/node@26.6.3': + resolution: {integrity: sha512-dsqMQQoeTLqu9wynDD00q573mNzso3IdQOAfHRJqLCcmCFPoGo9A1bDpUcv/9tnKpErQWv9uKeGfl37EIS02Yg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - - '@typescript-eslint/eslint-plugin@8.62.0': - resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} + '@typescript-eslint/eslint-plugin@8.70.1': + resolution: {integrity: sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.62.0 + '@typescript-eslint/parser': ^8.70.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.62.0': - resolution: {integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==} + '@typescript-eslint/parser@8.70.1': + resolution: {integrity: sha512-nO974WLllwhSFWQXnMLj6nDGa8f0khKEz1JzpPJ1u7Vm/4X1X6ZHajpoknU4bb41vJyMB0HHVyS2GqdhWfIXZw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.62.0': - resolution: {integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==} + '@typescript-eslint/project-service@8.70.1': + resolution: {integrity: sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.62.0': - resolution: {integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==} + '@typescript-eslint/scope-manager@8.70.1': + resolution: {integrity: sha512-Pa0EeSeAusQc1WbjQMac+YfenewYTBu0KjgYvkUKwhXaHUKbFog23Dm/rp0DX/6tyYOQ3Xl1a+3EcFNZynGHCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.62.0': - resolution: {integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==} + '@typescript-eslint/tsconfig-utils@8.70.1': + resolution: {integrity: sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.62.0': - resolution: {integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==} + '@typescript-eslint/type-utils@8.70.1': + resolution: {integrity: sha512-7zKTnyvaVWqzLZHPFQtX1hVHqgkMC+WebPWakNCSyrQVbIP1AM0L0TlBZtACldIRb6PptI8Odk+jyZ5kP3B1VA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.62.0': - resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} + '@typescript-eslint/types@8.70.1': + resolution: {integrity: sha512-Dm1ypdhhrGCTyyehxElhgJ6kgk8MVCv5qXdoOVqPr1uqk42jX8KjrZqhROvdShczA8qrDoYiOWn1ykWlx2k81Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.62.0': - resolution: {integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==} + '@typescript-eslint/typescript-estree@8.70.1': + resolution: {integrity: sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.62.0': - resolution: {integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==} + '@typescript-eslint/utils@8.70.1': + resolution: {integrity: sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.62.0': - resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} + '@typescript-eslint/visitor-keys@8.70.1': + resolution: {integrity: sha512-Vwj9lUIW5Xq3wQ9w6gv3R86g1hMK8f2zNOdGTAgeXUMMXFK78G9ruCjjqutHMNJc0+CH7LYRnHeUB9IT8wFmcw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitest/expect@4.1.11': - resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} - - '@vitest/mocker@4.1.11': - resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + '@vitest/mocker@5.0.2': + resolution: {integrity: sha512-Z5FS00Q1SJHkB35xATsmWGdQ5WA1/0MV3CDjqyv7GavHv1OfOj145MNfHOlHk7QLes21dKFDHr8EO2zvL+9WGA==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -488,50 +631,173 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.11': - resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + '@vitest/spy@5.0.2': + resolution: {integrity: sha512-Ijc7T1nT9efNb5LxvjaBrEqw3f/QwUv5EE0nKqZxgqsaV/FxAAZ8baGylA8X/Z2oS4Lp+K74Jr6dTJsDKxJDeg==} + + '@yuku-codegen/binding-android-arm64@0.10.2': + resolution: {integrity: sha512-Oc2KInVkPfUjEB4PeV6X0NvIoyYTzDe/WmqFrTwBqKs6YKnz4A7XwWQvJTb7M0rLz9a6WgpUUiiS5QKaCi4O/g==} + cpu: [arm64] + os: [android] + + '@yuku-codegen/binding-darwin-arm64@0.10.2': + resolution: {integrity: sha512-3H7eNPIHJndUJXZ4QUGBPq1zC6RGcUZfm7bymJes+/N7wTVWUn1bxZ9JcozYHpkWQNm9f23G8YWbaHD9aYH72A==} + cpu: [arm64] + os: [darwin] + + '@yuku-codegen/binding-darwin-x64@0.10.2': + resolution: {integrity: sha512-AJOUpR2s3LF9AWiiub/Uyc/UoXNTWcq8hK3cVI6fUSXtwh34dG21J6hRuNlO6JVJFTo4o3ScVvZOrh/YFfUEAA==} + cpu: [x64] + os: [darwin] + + '@yuku-codegen/binding-freebsd-x64@0.10.2': + resolution: {integrity: sha512-ms7DcZu87u5CiK/wMwvpKAvAmtaqKjCQIXNweMLypG6qbuiaOMQf1jpbB5+j46xBcgCovo8TQMcv0bCQLKIL9w==} + cpu: [x64] + os: [freebsd] + + '@yuku-codegen/binding-linux-arm-gnu@0.10.2': + resolution: {integrity: sha512-xJDpYAsKV5+eaiBhTYl05fvT6sst4PsCeuIFMRu9b0/WCSrNQPfCDtAQ5/MS6xNpsdujdZEPR+gmfWk3ZG5i3A==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm-musl@0.10.2': + resolution: {integrity: sha512-qfTkgd7AEx61l4K9VtXWCGTxc/fmXJ4ZheDz3i+/AAJUtg4sa0bPrc0VBxPggB/rayR8Z3+JfrBItuyanBJJ9Q==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-arm64-gnu@0.10.2': + resolution: {integrity: sha512-4e6Mifm/4UdjtU3D8mATIrvgP+xEiH8xtQOjd0zpd72XKWT7ug3sdyhq2utkkZFP6BvYp7SgZrI+aR4VeIOHdw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm64-musl@0.10.2': + resolution: {integrity: sha512-RdsJrUfDYFVV3JOmWFUWwSu31fa1APn12xDeIKxgl/YWxrabwtxsDBNjF2561c7tmcbiewdCUvngqRs8AyGVLA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-x64-gnu@0.10.2': + resolution: {integrity: sha512-mVzWimEPPreaPyXIUvxsHoJzvO7ckZ5j0LgQFHz04zQIRwt9A9T2hA7K5/jYjJKkMxWG/U2VjhGNwVhtyU+uqg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-x64-musl@0.10.2': + resolution: {integrity: sha512-Y77fyISurmr2mvO1yeq3u+x/WJbACgPR4w+lzEVx30ViCxZzIGrZPRN1yEdZ9xUNPNsIO5thBHIdRNG+UGUG+Q==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-win32-arm64@0.10.2': + resolution: {integrity: sha512-1+tGLyG0u5YYy0lev4ck7/0sd8xJ9SZde0dLut7qLDPZV5WVTV8x6OxNXUne/PGuHZyO1vK+txPQzzHOyXHGSw==} + cpu: [arm64] + os: [win32] + + '@yuku-codegen/binding-win32-x64@0.10.2': + resolution: {integrity: sha512-8a2SExRohRbwC0MY4VpOF0/RSckrJ2ASZqAor5/RYSJJaeadR93n10gZzcKT6pY9ukiSOIZCRKVRD2tH73T0qA==} + cpu: [x64] + os: [win32] + + '@yuku-parser/binding-android-arm64@0.10.2': + resolution: {integrity: sha512-2VPBU9fRGRAQ2xPAvghnec3oou5Nrxm2Bezhf+13UMspAxQSkF/32r+ySKXSwIPA5/RivumDJDxAxc301Sgicw==} + cpu: [arm64] + os: [android] + + '@yuku-parser/binding-darwin-arm64@0.10.2': + resolution: {integrity: sha512-LD+PMZE51tCYTOss5HBkm3/AE39MvcMDBfWJx7A4yDcjfNbAQDnHZKtzSOuqrswx+TQHY0ws5xn6+fWOwtmfBA==} + cpu: [arm64] + os: [darwin] - '@vitest/runner@4.1.11': - resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} + '@yuku-parser/binding-darwin-x64@0.10.2': + resolution: {integrity: sha512-mmZ8cND+AoIIMRERyMinlg5ApHxP23B9jH2B5wT7T+dliPa9rubLxneB/SUjFwyUjGaFnB5G7t4YvpfbO5zbkQ==} + cpu: [x64] + os: [darwin] - '@vitest/snapshot@4.1.11': - resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} + '@yuku-parser/binding-freebsd-x64@0.10.2': + resolution: {integrity: sha512-gVIjaaIddbRfAhHlC8N809wQWml7mxfSVnzaLtzGXObTeFTPAg/YVnQXt1UOhPM1ah5eG/8Y0RUlNpB4GVe7eQ==} + cpu: [x64] + os: [freebsd] - '@vitest/spy@4.1.11': - resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + '@yuku-parser/binding-linux-arm-gnu@0.10.2': + resolution: {integrity: sha512-q/XPPQQAPdlw05aPj30ygBhekmQryGOwxVraBgApjKK8yY1kNQgqq6XCYLF1WHSee+lhxclrTO7W0/bt7dR1GA==} + cpu: [arm] + os: [linux] + libc: [glibc] - '@vitest/utils@4.1.11': - resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + '@yuku-parser/binding-linux-arm-musl@0.10.2': + resolution: {integrity: sha512-A+Cb0I1hFF4wilTQpWs79k1aNnj4B2tkrHx3zsuUNF9BtVY2zPZ4yeQEM/zjXrS/qJlNMZVK9NrWJjwdpnTrfg==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-arm64-gnu@0.10.2': + resolution: {integrity: sha512-aGNSzqIqqphFwAdIFwVvKIyXD1Iy3CxrEJVIZAT87Ecyi4vCmmDD2v2l9h+Gd3/wSy3JZlOI792LJbKAjyy9rQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm64-musl@0.10.2': + resolution: {integrity: sha512-Ddl1sF0rtuCXyHGSOV6dcmdx+ETv1iD+IVFqQuOjzkJZWclxJxdBWX6ZJMRtTiGqGUTbqLEKiTXxpR/Bvqk+2A==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-x64-gnu@0.10.2': + resolution: {integrity: sha512-/nlcpR6IF5U+0m5L9wvAIXeQa2DT+BXuvqKDsTcOTlcc0B4dHNyqE5hTXsS4hAyimpy2ZK8A1zMNF5hTrjg2cg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-x64-musl@0.10.2': + resolution: {integrity: sha512-GX80dxTQD/M/OryyuxJcFzFENzry3cDFPvCFTyWogNWQH3fSHfMrNfpwpl1YzMos1eV9NygK5GSDG7VArQlb4w==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-win32-arm64@0.10.2': + resolution: {integrity: sha512-agePQBV4VHewiGU0ACSjscZ/hJd283f9JfAF19Gf1rI5+wy5tTgx4GS36i0b3xim15AQ4RCpDRosEvhLZ4zAOw==} + cpu: [arm64] + os: [win32] + + '@yuku-parser/binding-win32-x64@0.10.2': + resolution: {integrity: sha512-s8//CMpgL5+y1lvDCdyh1rwGI5+ytDJywFJRe1vnhI7n0j+caxshNucurikYLLVeQ2SYFex6aPrzgQxkabBQRA==} + cpu: [x64] + os: [win32] + + '@yuku-toolchain/types@0.10.2': + resolution: {integrity: sha512-sSeo4SSSToiS+sSD+bwn/s94EEcaLJ7tG5LCp8gFYC1G5VzxzX7fqB6m9RU1yMD8KTpu6zdU/I1NlQf8hVBJ9Q==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.3.0: - resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -540,9 +806,8 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} @@ -556,21 +821,30 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bidi-js@1.1.0: + resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - engines: {node: 18 || 20 || >=22} + brace-expansion@2.1.7: + resolution: {integrity: sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + cacheable@2.5.0: + resolution: {integrity: sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==} + camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} @@ -587,13 +861,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -602,11 +871,8 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} @@ -643,10 +909,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -659,20 +921,22 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + dts-resolver@3.0.0: + resolution: {integrity: sha512-1T1f+z+4tl9XD+m+0HBgWoL/nm0bOIffyWaUuUSBlFg/86IWvfx+wjNaO/ybU0AJzG9/Mi5hBUgGV6zCmWEN7Q==} + engines: {node: ^22.18.0 || >=24.0.0} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - entities@8.0.0: - resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + entities@8.1.0: + resolution: {integrity: sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==} engines: {node: '>=20.19.0'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} @@ -712,8 +976,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.5.0: - resolution: {integrity: sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==} + eslint@10.11.0: + resolution: {integrity: sha512-P7a6UEEqb9G95MYAtqkmsTbVXIYyzIfl6NGOIJk162PaahFxFyeGcrlXYFSiagECg4sEm8IseJdZBKR3rx6MsQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -738,9 +1002,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -748,9 +1009,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -768,8 +1026,8 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fastq@1.20.3: + resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -780,9 +1038,8 @@ packages: picomatch: optional: true - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + file-entry-cache@11.1.5: + resolution: {integrity: sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} @@ -796,17 +1053,11 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + flat-cache@6.1.23: + resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} @@ -816,9 +1067,9 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - get-east-asian-width@1.6.0: - resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} - engines: {node: '>=18'} + get-tsconfig@5.0.0-beta.6: + resolution: {integrity: sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==} + engines: {node: '>=20.20.0'} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -828,8 +1079,8 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - globals@17.7.0: - resolution: {integrity: sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==} + globals@17.12.0: + resolution: {integrity: sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==} engines: {node: '>=18'} globby@11.1.0: @@ -844,10 +1095,20 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + hashery@1.5.1: + resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==} + engines: {node: '>=20'} + hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} + hookified@1.15.1: + resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + + hookified@2.2.0: + resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -855,21 +1116,20 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - html-encoding-sniffer@6.0.0: - resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-encoding-sniffer@7.0.0: + resolution: {integrity: sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==} + engines: {node: ^22.13.0 || >=24.0.0} - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + ignore@7.0.10: + resolution: {integrity: sha512-HpbUakT7xp5miBUywCHf36ZEuAJNklBJDDsGpUIjMzOSmM8ELSfA9Sa/QDPeNeqeoN31u+UTCkL4klCOVvRm4Q==} engines: {node: '>= 4'} imurmurhash@0.1.4: @@ -880,6 +1140,10 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + index-to-position@1.2.0: + resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} + engines: {node: '>=18'} + irregular-plurals@3.5.0: resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==} engines: {node: '>=8'} @@ -887,8 +1151,8 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-core-module@2.16.2: - resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + is-core-module@2.17.0: + resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} engines: {node: '>= 0.4'} is-extglob@2.1.1: @@ -899,17 +1163,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -921,9 +1178,6 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -939,32 +1193,44 @@ packages: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - jsdom@29.1.1: - resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + js-yaml@5.4.2: + resolution: {integrity: sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==} + hasBin: true + + jsdom@30.1.1: + resolution: {integrity: sha512-FahmoPK5vbPc+jxV1iErMHmAZypCZ942NHF4+qqaWAuvaKKTBZxawnmAtrbGWLU7MtlxfqIP0qw6aSI+aWGtLg==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} peerDependencies: - canvas: ^3.0.0 + canvas: ^3.2.3 peerDependenciesMeta: canvas: optional: true - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} @@ -974,92 +1240,83 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@17.0.8: - resolution: {integrity: sha512-B2P/d+jVW0UXOQ0MVMLrB/9ydA1P+zz6jYfdrbbEd9ur3S2rcbduFWKiUCC02Sm5hbC8nrm7y24WuYMG54HfxA==} - engines: {node: '>=22.22.1'} - hasBin: true - - listr2@10.2.1: - resolution: {integrity: sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==} - engines: {node: '>=22.13.0'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1072,20 +1329,16 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - - lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} engines: {node: 20 || >=22} lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.4.2: + resolution: {integrity: sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==} map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} @@ -1110,18 +1363,18 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -1129,8 +1382,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + nanoid@3.3.19: + resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -1148,9 +1401,15 @@ packages: resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==} engines: {node: '>=12.20.0'} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} + obug@3.0.0: + resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==} + engines: {node: '>=12.20.0'} + + openapi-typescript@7.13.0: + resolution: {integrity: sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==} + hasBin: true + peerDependencies: + typescript: ^5.x optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} @@ -1180,6 +1439,10 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-json@8.3.0: + resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} + engines: {node: '>=18'} + parse5@8.0.1: resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} @@ -1198,9 +1461,6 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1208,38 +1468,38 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} - picomatch@4.0.7: resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} - playwright-core@1.61.0: - resolution: {integrity: sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==} - engines: {node: '>=18'} + playwright-core@1.63.0: + resolution: {integrity: sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==} + engines: {node: '>=20'} hasBin: true - playwright@1.61.0: - resolution: {integrity: sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==} - engines: {node: '>=18'} + playwright@1.63.0: + resolution: {integrity: sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==} + engines: {node: '>=20'} hasBin: true plur@4.0.0: resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==} engines: {node: '>=10'} - postcss@8.5.15: - resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + postcss@8.5.28: + resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.8.4: - resolution: {integrity: sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==} + prettier@3.9.9: + resolution: {integrity: sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==} engines: {node: '>=14'} hasBin: true @@ -1251,6 +1511,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qified@0.10.1: + resolution: {integrity: sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==} + engines: {node: '>=20'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1277,24 +1541,42 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.12: resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} engines: {node: '>= 0.4'} hasBin: true - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rolldown-plugin-dts@0.28.6: + resolution: {integrity: sha512-qKrFtBfRfR2hP233m7Ic9zf3wv6MSYdZghWKMdEO6dRYZGlNfINJAa1P5ZVvyHh3mrcd7IJQvIY8L9vnm+v5rQ==} + engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} + peerDependencies: + '@typescript/native-preview': '*' + '@volar/typescript': ~2.4.0 + '@vue/language-core': ~3.2.0 || ~3.3.0 + rolldown: ^1.2.0 + typescript: ^5.0.0 || ^6.0.0 || ~7.0.0 + vue-tsc: ~3.2.0 || ~3.3.0 + peerDependenciesMeta: + '@typescript/native-preview': + optional: true + '@volar/typescript': + optional: true + '@vue/language-core': + optional: true + typescript: + optional: true + vue-tsc: + optional: true - rolldown@1.0.3: - resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + rolldown@1.2.11: + resolution: {integrity: sha512-qpSwIyz0jHQq5qXBTNxFmE6664rJ7O+4TvPFOiOaBSrz8IOHc1koKKSqTM2H6u1UG1+TveuC6vaDHKXFOvb1Kw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1319,28 +1601,13 @@ packages: engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1354,43 +1621,28 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.23: - resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + spdx-license-ids@3.0.24: + resolution: {integrity: sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==} std-env@4.2.0: resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string-width@8.2.1: - resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} - engines: {node: '>=20'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1403,15 +1655,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} - engines: {node: '>=18'} + tinybench@6.2.0: + resolution: {integrity: sha512-78U2TlB2CnVenajOFzf3BKSm0J6oz5L0NV7g32LCPccvYc0lbWvys4d3uUUCS2B1N8PAf2+aekR8i1KbC3HO7Q==} + engines: {node: '>=20.0.0'} tinyexec@1.3.1: resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} @@ -1421,23 +1667,19 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinyrainbow@3.1.1: - resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} - engines: {node: '>=14.0.0'} - - tldts-core@7.4.4: - resolution: {integrity: sha512-vwVLJVvvpslm7vqAH7+XNj/neA/Ynq7DT2EEcMuwc5YzN5XaMyRAqxwU+uX3azZ1FQtB2gvrvnLnAEkvYlVdfg==} + tldts-core@7.4.16: + resolution: {integrity: sha512-MDolfaSJtlSK5Y0A1xl3277ekubZwobpBjugknDizI9O5Rm60a1m8k4ICK+MRsCDzPygT81mp3BBf5RKDlFRfA==} - tldts@7.4.4: - resolution: {integrity: sha512-kFXFK7O4WPextIUAOk8qtnw9dxR9UIXP9CjuH1cTBVBZMDeQcUPgr/IazGiw1B0Yiw5L75gHLWeW4iD793r90g==} + tldts@7.4.16: + resolution: {integrity: sha512-QwBER5KMR86IIjpIiO7H/Z3IMJPsZ1A6RKPAqzTTgOyUQUSt9FdnKcqhTaJmkY6HVrgouZHZR0ncK5QxvmnQeg==} hasBin: true to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tough-cookie@6.0.1: - resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} tr46@6.0.0: @@ -1459,9 +1701,6 @@ packages: engines: {node: '>=14.16'} hasBin: true - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1482,8 +1721,12 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - typescript-eslint@8.62.0: - resolution: {integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript-eslint@8.70.1: + resolution: {integrity: sha512-AcWG7KDjZ2THNXsgwttMaGmzVi0VFRlFYfqFHYQRbDpF3owuYbuiL8c7UUrd2k8s3PoSfIQrWfrGXfcElrWLYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -1494,12 +1737,15 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@8.3.0: - resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + undici@8.11.2: + resolution: {integrity: sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==} + engines: {node: '>=22.19.0'} - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} - engines: {node: '>=20.18.1'} + uri-js-replace@1.0.1: + resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1507,13 +1753,13 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - vite@8.0.16: - resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + vite@8.3.1: + resolution: {integrity: sha512-/bvH9E9tmCXRGp2uXY3WbOldqpTwFkbha/8ANaEQ6VkxhH60KyqLwgZq6lG2y+4uT55x9+9eUHMpQ7uGnOCKjA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.18 + '@vitejs/devtools': ^0.7.1 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -1550,23 +1796,23 @@ packages: yaml: optional: true - vitest@4.1.11: - resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + vitest@5.0.2: + resolution: {integrity: sha512-7MQrx9pDv5aHiUcovIb/70Ys3tgtkUVgCtledvKdCmEO+/1Dicq5ZqoSxOW034m03oqC+oHOKui2dM6qtMLoJg==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.11 - '@vitest/browser-preview': 4.1.11 - '@vitest/browser-webdriverio': 4.1.11 - '@vitest/coverage-istanbul': 4.1.11 - '@vitest/coverage-v8': 4.1.11 - '@vitest/ui': 4.1.11 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.2 + '@vitest/browser-preview': 5.0.2 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.2 + '@vitest/coverage-v8': 5.0.2 + '@vitest/ui': 5.0.2 happy-dom: '*' jsdom: '*' - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -1591,9 +1837,9 @@ packages: jsdom: optional: true - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} + w3c-xmlserializer@6.0.0: + resolution: {integrity: sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} webidl-conversions@8.0.1: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} @@ -1607,28 +1853,24 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@17.1.2: + resolution: {integrity: sha512-TEZA+Zqxin7Jjsm2cjRohCmen5awh+hT6Zi3VZdqZlNRk7zvOI/9WpBFg/DWlA56bWnzwm6DuB8NS0EsxQH9uQ==} + engines: {node: ^22.14.0 || >=24.0.0} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} + why-is-node-running@3.2.2: + resolution: {integrity: sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A==} + engines: {node: '>=20.11'} hasBin: true word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrap-ansi@10.0.0: - resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} - engines: {node: '>=20'} - - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -1639,8 +1881,11 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.9.0: - resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} engines: {node: '>= 14.6'} hasBin: true @@ -1648,31 +1893,39 @@ packages: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yuku-ast@0.10.2: + resolution: {integrity: sha512-UnG9mA6giglCvSErft2/40TVFX750Sj1xgwddPLpG7J7rlr/P1wPADg9G2RK+d/1tNLtRVoLdMMOMVBB9561TQ==} + + yuku-codegen@0.10.2: + resolution: {integrity: sha512-hentl2dtrF6cPjiAirtkfxfFZBA6Hdm61UqRJ7cA0qrlDNMk9PZGOjw5w1mx3E0hu/6pHcJF4dJW+D0SXHPZOA==} + + yuku-parser@0.10.2: + resolution: {integrity: sha512-CgaU0/PPjCAIEZ3WQroosOxTY3eeKldAN3h+vk8pMNz4+jl1CZzBR4pW+K/rRPF112VooCL5FdjJoiMNjDrL2A==} + snapshots: - '@asamuzakjp/css-color@5.1.11': + '@asamuzakjp/css-color@7.1.2': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.8(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-calc': 3.4.1(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-color-parser': 4.2.4(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.1(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + lru-cache: 11.5.3 - '@asamuzakjp/dom-selector@7.1.1': + '@asamuzakjp/dom-selector@9.2.2': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@asamuzakjp/nwsapi': 2.3.9 - bidi-js: 1.0.3 + bidi-js: 1.1.0 css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 - - '@asamuzakjp/generational-cache@1.0.1': {} - - '@asamuzakjp/nwsapi@2.3.9': {} + lru-cache: 11.5.3 '@babel/code-frame@7.29.7': dependencies: @@ -1686,62 +1939,58 @@ snapshots: dependencies: css-tree: 3.2.1 - '@csstools/color-helpers@6.0.2': {} - - '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': - dependencies: - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-color-parser@4.1.8(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@cacheable/memory@2.2.0': dependencies: - '@csstools/color-helpers': 6.0.2 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@cacheable/utils': 2.5.0 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.1 + keyv: 5.6.0 - '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + '@cacheable/utils@2.5.0': dependencies: - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': - optionalDependencies: - css-tree: 3.2.1 + hashery: 1.5.1 + keyv: 5.6.0 - '@csstools/css-tokenizer@4.0.0': {} + '@csstools/color-helpers@6.1.2': {} - '@emnapi/core@1.10.0': + '@csstools/css-calc@3.4.1(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': dependencies: - '@emnapi/wasi-threads': 1.2.1 - tslib: 2.8.1 - optional: true + '@csstools/css-parser-algorithms': 4.0.1(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 - '@emnapi/runtime@1.10.0': + '@csstools/css-color-parser@4.2.4(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': dependencies: - tslib: 2.8.1 - optional: true + '@csstools/color-helpers': 6.1.2 + '@csstools/css-calc': 3.4.1(@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.1(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 - '@emnapi/wasi-threads@1.2.1': + '@csstools/css-parser-algorithms@4.0.1(@csstools/css-tokenizer@4.0.2)': dependencies: - tslib: 2.8.1 - optional: true + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-syntax-patches-for-csstree@1.1.14(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 - '@eslint-community/eslint-utils@4.9.1(eslint@10.5.0)': + '@csstools/css-tokenizer@4.0.2': {} + + '@eslint-community/eslint-utils@4.10.1(eslint@10.11.0(supports-color@10.2.2))': dependencies: - eslint: 10.5.0 + eslint: 10.11.0(supports-color@10.2.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.23.5': + '@eslint/config-array@0.23.5(supports-color@10.2.2)': dependencies: '@eslint/object-schema': 3.0.5 - debug: 4.4.3 - minimatch: 10.2.5 + debug: 4.4.3(supports-color@10.2.2) + minimatch: 10.2.6 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.6.0': + '@eslint/config-helpers@0.7.0': dependencies: '@eslint/core': 1.2.1 @@ -1749,18 +1998,18 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.5.0)': + '@eslint/js@10.0.1(eslint@10.11.0(supports-color@10.2.2))': optionalDependencies: - eslint: 10.5.0 + eslint: 10.11.0(supports-color@10.2.2) '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.7.2': + '@eslint/plugin-kit@0.7.3': dependencies: '@eslint/core': 1.2.1 levn: 0.4.1 - '@exodus/bytes@1.15.1': {} + '@exodus/bytes@1.16.0': {} '@humanfs/core@0.19.2': dependencies: @@ -1780,16 +2029,24 @@ snapshots: '@jest/schemas@29.6.3': dependencies: - '@sinclair/typebox': 0.27.10 + '@sinclair/typebox': 0.27.12 - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/resolve-uri@3.1.2': {} - '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.3 - optional: true + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@keyv/bigmap@1.3.1(keyv@5.6.0)': + dependencies: + hashery: 1.5.1 + hookified: 1.15.1 + keyv: 5.6.0 + + '@keyv/serialize@1.1.1': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -1801,105 +2058,88 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 + fastq: 1.20.3 + + '@oxc-project/types@0.151.0': {} + + '@playwright/test@1.63.0': + dependencies: + playwright: 1.63.0 + + '@redocly/ajv@8.11.2': + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js-replace: 1.0.1 - '@oxc-project/types@0.133.0': {} + '@redocly/config@0.22.0': {} - '@playwright/test@1.61.0': + '@redocly/openapi-core@1.34.20(supports-color@10.2.2)': dependencies: - playwright: 1.61.0 + '@redocly/ajv': 8.11.2 + '@redocly/config': 0.22.0 + colorette: 1.4.0 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + js-levenshtein: 1.1.6 + js-yaml: 4.3.2 + minimatch: 5.1.9 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - supports-color - '@rolldown/binding-android-arm64@1.0.3': + '@rolldown/binding-android-arm-eabi@1.2.11': optional: true - '@rolldown/binding-darwin-arm64@1.0.3': + '@rolldown/binding-android-arm64@1.2.11': optional: true - '@rolldown/binding-darwin-x64@1.0.3': + '@rolldown/binding-darwin-arm64@1.2.11': optional: true - '@rolldown/binding-freebsd-x64@1.0.3': + '@rolldown/binding-darwin-x64@1.2.11': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + '@rolldown/binding-freebsd-x64@1.2.11': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.3': + '@rolldown/binding-linux-arm-gnueabihf@1.2.11': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.3': + '@rolldown/binding-linux-arm64-gnu@1.2.11': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.3': + '@rolldown/binding-linux-arm64-musl@1.2.11': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.3': + '@rolldown/binding-linux-ppc64-gnu@1.2.11': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.3': + '@rolldown/binding-linux-s390x-gnu@1.2.11': optional: true - '@rolldown/binding-linux-x64-musl@1.0.3': + '@rolldown/binding-linux-x64-gnu@1.2.11': optional: true - '@rolldown/binding-openharmony-arm64@1.0.3': + '@rolldown/binding-linux-x64-musl@1.2.11': optional: true - '@rolldown/binding-wasm32-wasi@1.0.3': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@rolldown/binding-openharmony-arm64@1.2.11': optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.3': + '@rolldown/binding-win32-arm64-msvc@1.2.11': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.3': + '@rolldown/binding-win32-x64-msvc@1.2.11': optional: true '@rolldown/pluginutils@1.0.1': {} - '@rollup/plugin-commonjs@29.0.3': - dependencies: - '@rollup/pluginutils': 5.4.0 - commondir: 1.0.1 - estree-walker: 2.0.2 - fdir: 6.5.0(picomatch@4.0.4) - is-reference: 1.2.1 - magic-string: 0.30.21 - picomatch: 4.0.4 - - '@rollup/plugin-node-resolve@16.0.3': - dependencies: - '@rollup/pluginutils': 5.4.0 - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.12 - - '@rollup/plugin-replace@6.0.3': - dependencies: - '@rollup/pluginutils': 5.4.0 - magic-string: 0.30.21 - - '@rollup/pluginutils@5.4.0': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.4 - - '@sinclair/typebox@0.27.10': {} - - '@standard-schema/spec@1.1.0': {} + '@sinclair/typebox@0.27.12': {} '@tsd/typescript@5.9.3': {} - '@tybys/wasm-util@0.10.3': - dependencies: - tslib: 2.8.1 - optional: true - '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -1920,82 +2160,80 @@ snapshots: '@types/minimist@1.2.5': {} - '@types/node@26.0.0': + '@types/node@26.6.3': dependencies: - undici-types: 8.3.0 + undici-types: 8.9.0 '@types/normalize-package-data@2.4.4': {} - '@types/resolve@1.20.2': {} - - '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/type-utils': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.62.0 - eslint: 10.5.0 - ignore: 7.0.5 + '@typescript-eslint/parser': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.1 + '@typescript-eslint/type-utils': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.1 + eslint: 10.11.0(supports-color@10.2.2) + ignore: 7.0.10 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@6.0.3)': + '@typescript-eslint/parser@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3 - eslint: 10.5.0 + '@typescript-eslint/scope-manager': 8.70.1 + '@typescript-eslint/types': 8.70.1 + '@typescript-eslint/typescript-estree': 8.70.1(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.1 + debug: 4.4.3(supports-color@10.2.2) + eslint: 10.11.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.62.0(typescript@6.0.3)': + '@typescript-eslint/project-service@8.70.1(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) - '@typescript-eslint/types': 8.62.0 - debug: 4.4.3 + '@typescript-eslint/tsconfig-utils': 8.70.1(typescript@6.0.3) + '@typescript-eslint/types': 8.70.1 + debug: 4.4.3(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.62.0': + '@typescript-eslint/scope-manager@8.70.1': dependencies: - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/visitor-keys': 8.62.0 + '@typescript-eslint/types': 8.70.1 + '@typescript-eslint/visitor-keys': 8.70.1 - '@typescript-eslint/tsconfig-utils@8.62.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.70.1(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.62.0(eslint@10.5.0)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - debug: 4.4.3 - eslint: 10.5.0 + '@typescript-eslint/types': 8.70.1 + '@typescript-eslint/typescript-estree': 8.70.1(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + debug: 4.4.3(supports-color@10.2.2) + eslint: 10.11.0(supports-color@10.2.2) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.62.0': {} + '@typescript-eslint/types@8.70.1': {} - '@typescript-eslint/typescript-estree@8.62.0(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.70.1(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.62.0(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3 - minimatch: 10.2.5 + '@typescript-eslint/project-service': 8.70.1(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.70.1(typescript@6.0.3) + '@typescript-eslint/types': 8.70.1 + '@typescript-eslint/visitor-keys': 8.70.1 + debug: 4.4.3(supports-color@10.2.2) + minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -2003,68 +2241,114 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.62.0(eslint@10.5.0)(typescript@6.0.3)': + '@typescript-eslint/utils@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - eslint: 10.5.0 + '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0(supports-color@10.2.2)) + '@typescript-eslint/scope-manager': 8.70.1 + '@typescript-eslint/types': 8.70.1 + '@typescript-eslint/typescript-estree': 8.70.1(supports-color@10.2.2)(typescript@6.0.3) + eslint: 10.11.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.62.0': + '@typescript-eslint/visitor-keys@8.70.1': dependencies: - '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/types': 8.70.1 eslint-visitor-keys: 5.0.1 - '@vitest/expect@4.1.11': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - chai: 6.2.2 - tinyrainbow: 3.1.1 - - '@vitest/mocker@4.1.11(vite@8.0.16(@types/node@26.0.0)(yaml@2.9.0))': + '@vitest/mocker@5.0.2(vite@8.3.1(@types/node@26.6.3)(yaml@2.9.1))': dependencies: - '@vitest/spy': 4.1.11 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.2 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.4.2 optionalDependencies: - vite: 8.0.16(@types/node@26.0.0)(yaml@2.9.0) + vite: 8.3.1(@types/node@26.6.3)(yaml@2.9.1) - '@vitest/pretty-format@4.1.11': - dependencies: - tinyrainbow: 3.1.1 + '@vitest/spy@5.0.2': {} - '@vitest/runner@4.1.11': - dependencies: - '@vitest/utils': 4.1.11 - pathe: 2.0.3 + '@yuku-codegen/binding-android-arm64@0.10.2': + optional: true - '@vitest/snapshot@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pathe: 2.0.3 + '@yuku-codegen/binding-darwin-arm64@0.10.2': + optional: true - '@vitest/spy@4.1.11': {} + '@yuku-codegen/binding-darwin-x64@0.10.2': + optional: true - '@vitest/utils@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.1 + '@yuku-codegen/binding-freebsd-x64@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-arm-gnu@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-arm-musl@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-arm64-gnu@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-arm64-musl@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-x64-gnu@0.10.2': + optional: true + + '@yuku-codegen/binding-linux-x64-musl@0.10.2': + optional: true + + '@yuku-codegen/binding-win32-arm64@0.10.2': + optional: true + + '@yuku-codegen/binding-win32-x64@0.10.2': + optional: true + + '@yuku-parser/binding-android-arm64@0.10.2': + optional: true + + '@yuku-parser/binding-darwin-arm64@0.10.2': + optional: true + + '@yuku-parser/binding-darwin-x64@0.10.2': + optional: true + + '@yuku-parser/binding-freebsd-x64@0.10.2': + optional: true + + '@yuku-parser/binding-linux-arm-gnu@0.10.2': + optional: true + + '@yuku-parser/binding-linux-arm-musl@0.10.2': + optional: true + + '@yuku-parser/binding-linux-arm64-gnu@0.10.2': + optional: true + + '@yuku-parser/binding-linux-arm64-musl@0.10.2': + optional: true - acorn-jsx@5.3.2(acorn@8.17.0): + '@yuku-parser/binding-linux-x64-gnu@0.10.2': + optional: true + + '@yuku-parser/binding-linux-x64-musl@0.10.2': + optional: true + + '@yuku-parser/binding-win32-arm64@0.10.2': + optional: true + + '@yuku-parser/binding-win32-x64@0.10.2': + optional: true + + '@yuku-toolchain/types@0.10.2': {} + + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: - acorn: 8.17.0 + acorn: 8.18.0 + + acorn@8.18.0: {} - acorn@8.17.0: {} + agent-base@7.1.4: {} ajv@6.15.0: dependencies: @@ -2073,25 +2357,21 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} + argparse@2.0.1: {} array-union@2.1.0: {} @@ -2099,13 +2379,19 @@ snapshots: assertion-error@2.0.1: {} + balanced-match@1.0.2: {} + balanced-match@4.0.4: {} - bidi-js@1.0.3: + bidi-js@1.1.0: dependencies: require-from-string: 2.0.2 - brace-expansion@5.0.6: + brace-expansion@2.1.7: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.12: dependencies: balanced-match: 4.0.4 @@ -2113,6 +2399,14 @@ snapshots: dependencies: fill-range: 7.1.1 + cacheable@2.5.0: + dependencies: + '@cacheable/memory': 2.2.0 + '@cacheable/utils': 2.5.0 + hookified: 1.15.1 + keyv: 5.6.0 + qified: 0.10.1 + camelcase-keys@6.2.2: dependencies: camelcase: 5.3.1 @@ -2128,14 +2422,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-truncate@5.2.0: - dependencies: - slice-ansi: 8.0.0 - string-width: 8.2.1 + change-case@5.4.4: {} color-convert@2.0.1: dependencies: @@ -2143,9 +2430,7 @@ snapshots: color-name@1.1.4: {} - commondir@1.0.1: {} - - convert-source-map@2.0.0: {} + colorette@1.4.0: {} cross-spawn@7.0.6: dependencies: @@ -2165,9 +2450,11 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' - debug@4.4.3: + debug@4.4.3(supports-color@10.2.2): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 10.2.2 decamelize-keys@1.1.1: dependencies: @@ -2180,8 +2467,6 @@ snapshots: deep-is@0.1.4: {} - deepmerge@4.3.1: {} - detect-libc@2.1.2: {} diff-sequences@29.6.3: {} @@ -2190,13 +2475,11 @@ snapshots: dependencies: path-type: 4.0.0 - emoji-regex@10.6.0: {} + dts-resolver@3.0.0: {} emoji-regex@8.0.0: {} - entities@8.0.0: {} - - environment@1.1.0: {} + entities@8.1.0: {} error-ex@1.3.4: dependencies: @@ -2208,9 +2491,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.5.0): + eslint-config-prettier@10.1.8(eslint@10.11.0(supports-color@10.2.2)): dependencies: - eslint: 10.5.0 + eslint: 10.11.0(supports-color@10.2.2) eslint-formatter-pretty@4.1.0: dependencies: @@ -2236,21 +2519,21 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.5.0: + eslint@10.11.0(supports-color@10.2.2): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0(supports-color@10.2.2)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.5 - '@eslint/config-helpers': 0.6.0 + '@eslint/config-array': 0.23.5(supports-color@10.2.2) + '@eslint/config-helpers': 0.7.0 '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.2 + '@eslint/plugin-kit': 0.7.3 '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) escape-string-regexp: 4.0.0 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -2258,14 +2541,14 @@ snapshots: esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 + file-entry-cache: 11.1.5 find-up: 5.0.0 glob-parent: 6.0.2 ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -2273,8 +2556,8 @@ snapshots: espree@11.2.0: dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 5.0.1 esquery@1.7.0: @@ -2287,16 +2570,12 @@ snapshots: estraverse@5.3.0: {} - estree-walker@2.0.2: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 esutils@2.0.3: {} - eventemitter3@5.0.4: {} - expect-type@1.4.0: {} fast-deep-equal@3.1.3: {} @@ -2313,17 +2592,17 @@ snapshots: fast-levenshtein@2.0.6: {} - fastq@1.20.1: + fastq@1.20.3: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.7 - file-entry-cache@8.0.0: + file-entry-cache@11.1.5: dependencies: - flat-cache: 4.0.1 + flat-cache: 6.1.23 fill-range@7.1.1: dependencies: @@ -2339,22 +2618,22 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@4.0.1: + flat-cache@6.1.23: dependencies: - flatted: 3.4.2 - keyv: 4.5.4 + cacheable: 2.5.0 + flatted: 3.4.4 + hookified: 1.15.1 - flatted@3.4.2: {} - - fsevents@2.3.2: - optional: true + flatted@3.4.4: {} fsevents@2.3.3: optional: true function-bind@1.1.2: {} - get-east-asian-width@1.6.0: {} + get-tsconfig@5.0.0-beta.6: + dependencies: + resolve-pkg-maps: 1.0.0 glob-parent@5.1.2: dependencies: @@ -2364,7 +2643,7 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@17.7.0: {} + globals@17.12.0: {} globby@11.1.0: dependencies: @@ -2379,37 +2658,52 @@ snapshots: has-flag@4.0.0: {} + hashery@1.5.1: + dependencies: + hookified: 1.15.1 + hasown@2.0.4: dependencies: function-bind: 1.1.2 + hookified@1.15.1: {} + + hookified@2.2.0: {} + hosted-git-info@2.8.9: {} hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 - html-encoding-sniffer@6.0.0: + html-encoding-sniffer@7.0.0: dependencies: - '@exodus/bytes': 1.15.1 + '@exodus/bytes': 1.16.0 transitivePeerDependencies: - '@noble/hashes' - husky@9.1.7: {} + https-proxy-agent@7.0.6(supports-color@10.2.2): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@10.2.2) + transitivePeerDependencies: + - supports-color ignore@5.3.2: {} - ignore@7.0.5: {} + ignore@7.0.10: {} imurmurhash@0.1.4: {} indent-string@4.0.0: {} + index-to-position@1.2.0: {} + irregular-plurals@3.5.0: {} is-arrayish@0.2.1: {} - is-core-module@2.16.2: + is-core-module@2.17.0: dependencies: hasown: 2.0.4 @@ -2417,26 +2711,16 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.6.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - is-module@1.0.0: {} - is-number@7.0.0: {} is-plain-obj@1.1.0: {} is-potential-custom-element-name@1.0.1: {} - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.9 - is-unicode-supported@0.1.0: {} isexe@2.0.0: {} @@ -2450,45 +2734,54 @@ snapshots: jest-get-type@29.6.3: {} + js-levenshtein@1.1.6: {} + js-tokens@4.0.0: {} - jsdom@29.1.1: + js-yaml@4.3.2: dependencies: - '@asamuzakjp/css-color': 5.1.11 - '@asamuzakjp/dom-selector': 7.1.1 + argparse: 2.0.1 + + js-yaml@5.4.2: + dependencies: + argparse: 2.0.1 + + jsdom@30.1.1: + dependencies: + '@asamuzakjp/css-color': 7.1.2 + '@asamuzakjp/dom-selector': 9.2.2 '@bramus/specificity': 2.4.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) - '@exodus/bytes': 1.15.1 + '@csstools/css-syntax-patches-for-csstree': 1.1.14(css-tree@3.2.1) + '@exodus/bytes': 1.16.0 css-tree: 3.2.1 data-urls: 7.0.0 decimal.js: 10.6.0 - html-encoding-sniffer: 6.0.0 + html-encoding-sniffer: 7.0.0 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.1 + lru-cache: 11.5.3 parse5: 8.0.1 saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 6.0.1 - undici: 7.28.0 - w3c-xmlserializer: 5.0.0 + tough-cookie: 6.0.2 + undici: 8.11.2 + w3c-xmlserializer: 6.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1 + whatwg-url: 17.1.2 xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} - keyv@4.5.4: + keyv@5.6.0: dependencies: - json-buffer: 3.0.1 + '@keyv/serialize': 1.1.1 kind-of@6.0.3: {} @@ -2497,74 +2790,57 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 lines-and-columns@1.2.4: {} - lint-staged@17.0.8: - dependencies: - listr2: 10.2.1 - picomatch: 4.0.4 - string-argv: 0.3.2 - tinyexec: 1.2.4 - optionalDependencies: - yaml: 2.9.0 - - listr2@10.2.1: - dependencies: - cli-truncate: 5.2.0 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 10.0.0 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -2578,23 +2854,15 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - - lru-cache@11.5.1: {} + lru-cache@11.5.3: {} lru-cache@6.0.0: dependencies: yallist: 4.0.0 - magic-string@0.30.21: + magic-string@1.4.2: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 map-obj@1.0.1: {} @@ -2624,13 +2892,15 @@ snapshots: braces: 3.0.3 picomatch: 2.3.2 - mimic-function@5.0.1: {} - min-indent@1.0.1: {} - minimatch@10.2.5: + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + + minimatch@5.1.9: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 2.1.7 minimist-options@4.1.0: dependencies: @@ -2640,7 +2910,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.15: {} + nanoid@3.3.19: {} natural-compare@1.4.0: {} @@ -2654,15 +2924,23 @@ snapshots: normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.16.2 + is-core-module: 2.17.0 semver: 7.8.5 validate-npm-package-license: 3.0.4 obug@2.2.1: {} - onetime@7.0.0: + obug@3.0.0: {} + + openapi-typescript@7.13.0(typescript@6.0.3): dependencies: - mimic-function: 5.0.1 + '@redocly/openapi-core': 1.34.20(supports-color@10.2.2) + ansi-colors: 4.1.3 + change-case: 5.4.4 + parse-json: 8.3.0 + supports-color: 10.2.2 + typescript: 6.0.3 + yargs-parser: 21.1.1 optionator@0.9.4: dependencies: @@ -2698,9 +2976,15 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-json@8.3.0: + dependencies: + '@babel/code-frame': 7.29.7 + index-to-position: 1.2.0 + type-fest: 4.41.0 + parse5@8.0.1: dependencies: - entities: 8.0.0 + entities: 8.1.0 path-exists@4.0.0: {} @@ -2710,37 +2994,33 @@ snapshots: path-type@4.0.0: {} - pathe@2.0.3: {} - picocolors@1.1.1: {} picomatch@2.3.2: {} - picomatch@4.0.4: {} - picomatch@4.0.7: {} - playwright-core@1.61.0: {} + playwright-core@1.63.0: {} - playwright@1.61.0: + playwright@1.63.0: dependencies: - playwright-core: 1.61.0 - optionalDependencies: - fsevents: 2.3.2 + playwright-core: 1.63.0 plur@4.0.0: dependencies: irregular-plurals: 3.5.0 - postcss@8.5.15: + pluralize@8.0.0: {} + + postcss@8.5.28: dependencies: - nanoid: 3.3.15 + nanoid: 3.3.19 picocolors: 1.1.1 source-map-js: 1.2.1 prelude-ls@1.2.1: {} - prettier@3.8.4: {} + prettier@3.9.9: {} pretty-format@29.7.0: dependencies: @@ -2750,6 +3030,10 @@ snapshots: punycode@2.3.1: {} + qified@0.10.1: + dependencies: + hookified: 2.2.0 + queue-microtask@1.2.3: {} quick-lru@4.0.1: {} @@ -2776,42 +3060,51 @@ snapshots: require-from-string@2.0.2: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.12: dependencies: es-errors: 1.3.0 - is-core-module: 2.16.2 + is-core-module: 2.17.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - reusify@1.1.0: {} - rfdc@1.4.1: {} + rolldown-plugin-dts@0.28.6(rolldown@1.2.11)(typescript@6.0.3): + dependencies: + dts-resolver: 3.0.0 + get-tsconfig: 5.0.0-beta.6 + obug: 3.0.0 + rolldown: 1.2.11 + yuku-ast: 0.10.2 + yuku-codegen: 0.10.2 + yuku-parser: 0.10.2 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - oxc-resolver - rolldown@1.0.3: + rolldown@1.2.11: dependencies: - '@oxc-project/types': 0.133.0 + '@oxc-project/types': 0.151.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.3 - '@rolldown/binding-darwin-arm64': 1.0.3 - '@rolldown/binding-darwin-x64': 1.0.3 - '@rolldown/binding-freebsd-x64': 1.0.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.3 - '@rolldown/binding-linux-arm64-musl': 1.0.3 - '@rolldown/binding-linux-ppc64-gnu': 1.0.3 - '@rolldown/binding-linux-s390x-gnu': 1.0.3 - '@rolldown/binding-linux-x64-gnu': 1.0.3 - '@rolldown/binding-linux-x64-musl': 1.0.3 - '@rolldown/binding-openharmony-arm64': 1.0.3 - '@rolldown/binding-wasm32-wasi': 1.0.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.3 - '@rolldown/binding-win32-x64-msvc': 1.0.3 + '@rolldown/binding-android-arm-eabi': 1.2.11 + '@rolldown/binding-android-arm64': 1.2.11 + '@rolldown/binding-darwin-arm64': 1.2.11 + '@rolldown/binding-darwin-x64': 1.2.11 + '@rolldown/binding-freebsd-x64': 1.2.11 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.11 + '@rolldown/binding-linux-arm64-gnu': 1.2.11 + '@rolldown/binding-linux-arm64-musl': 1.2.11 + '@rolldown/binding-linux-ppc64-gnu': 1.2.11 + '@rolldown/binding-linux-s390x-gnu': 1.2.11 + '@rolldown/binding-linux-x64-gnu': 1.2.11 + '@rolldown/binding-linux-x64-musl': 1.2.11 + '@rolldown/binding-openharmony-arm64': 1.2.11 + '@rolldown/binding-win32-arm64-msvc': 1.2.11 + '@rolldown/binding-win32-x64-msvc': 1.2.11 run-parallel@1.2.0: dependencies: @@ -2831,73 +3124,42 @@ snapshots: shebang-regex@3.0.0: {} - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - slash@3.0.0: {} - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - slice-ansi@8.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - source-map-js@1.2.1: {} spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.23 + spdx-license-ids: 3.0.24 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.23 - - spdx-license-ids@3.0.23: {} + spdx-license-ids: 3.0.24 - stackback@0.0.2: {} + spdx-license-ids@3.0.24: {} std-env@4.2.0: {} - string-argv@0.3.2: {} - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - - string-width@8.2.1: - dependencies: - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 + supports-color@10.2.2: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -2909,34 +3171,28 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - symbol-tree@3.2.4: {} - - tinybench@2.9.0: {} - - tinyexec@1.2.4: {} + tinybench@6.2.0: {} tinyexec@1.3.1: {} tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - - tinyrainbow@3.1.1: {} + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 - tldts-core@7.4.4: {} + tldts-core@7.4.16: {} - tldts@7.4.4: + tldts@7.4.16: dependencies: - tldts-core: 7.4.4 + tldts-core: 7.4.16 to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - tough-cookie@6.0.1: + tough-cookie@6.0.2: dependencies: - tldts: 7.4.4 + tldts: 7.4.16 tr46@6.0.0: dependencies: @@ -2958,9 +3214,6 @@ snapshots: path-exists: 4.0.0 read-pkg-up: 7.0.1 - tslib@2.8.1: - optional: true - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -2973,22 +3226,26 @@ snapshots: type-fest@0.8.1: {} - typescript-eslint@8.62.0(eslint@10.5.0)(typescript@6.0.3): + type-fest@4.41.0: {} + + typescript-eslint@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3) - '@typescript-eslint/parser': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@6.0.3) - eslint: 10.5.0 + '@typescript-eslint/eslint-plugin': 8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/parser': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.70.1(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.1(eslint@10.11.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + eslint: 10.11.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color typescript@6.0.3: {} - undici-types@8.3.0: {} + undici-types@8.9.0: {} + + undici@8.11.2: {} - undici@7.28.0: {} + uri-js-replace@1.0.1: {} uri-js@4.4.1: dependencies: @@ -2999,47 +3256,41 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite@8.0.16(@types/node@26.0.0)(yaml@2.9.0): + vite@8.3.1(@types/node@26.6.3)(yaml@2.9.1): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.0.3 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.28 + rolldown: 1.2.11 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 26.0.0 + '@types/node': 26.6.3 fsevents: 2.3.3 - yaml: 2.9.0 + yaml: 2.9.1 - vitest@4.1.11(@types/node@26.0.0)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.0.0)(yaml@2.9.0)): + vitest@5.0.2(@types/node@26.6.3)(jsdom@30.1.1)(vite@8.3.1(@types/node@26.6.3)(yaml@2.9.1)): dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.0.16(@types/node@26.0.0)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.2(vite@8.3.1(@types/node@26.6.3)(yaml@2.9.1)) + chai: 6.2.2 es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 + magic-string: 1.4.2 obug: 2.2.1 - pathe: 2.0.3 picomatch: 4.0.7 std-env: 4.2.0 - tinybench: 2.9.0 + tinybench: 6.2.0 tinyexec: 1.3.1 tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 - vite: 8.0.16(@types/node@26.0.0)(yaml@2.9.0) - why-is-node-running: 2.3.0 + vite: 8.3.1(@types/node@26.6.3)(yaml@2.9.1) + why-is-node-running: 3.2.2 optionalDependencies: - '@types/node': 26.0.0 - jsdom: 29.1.1 + '@types/node': 26.6.3 + jsdom: 30.1.1 transitivePeerDependencies: - msw - w3c-xmlserializer@5.0.0: + w3c-xmlserializer@6.0.0: dependencies: xml-name-validator: 5.0.0 @@ -3049,7 +3300,15 @@ snapshots: whatwg-url@16.0.1: dependencies: - '@exodus/bytes': 1.15.1 + '@exodus/bytes': 1.16.0 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + whatwg-url@17.1.2: + dependencies: + '@exodus/bytes': 1.16.0 tr46: 6.0.0 webidl-conversions: 8.0.1 transitivePeerDependencies: @@ -3059,34 +3318,62 @@ snapshots: dependencies: isexe: 2.0.0 - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 + why-is-node-running@3.2.2: {} word-wrap@1.2.5: {} - wrap-ansi@10.0.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 8.2.1 - strip-ansi: 7.2.0 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} yallist@4.0.0: {} - yaml@2.9.0: + yaml-ast-parser@0.0.43: {} + + yaml@2.9.1: optional: true yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + yocto-queue@0.1.0: {} + + yuku-ast@0.10.2: + dependencies: + '@yuku-toolchain/types': 0.10.2 + + yuku-codegen@0.10.2: + dependencies: + '@yuku-toolchain/types': 0.10.2 + optionalDependencies: + '@yuku-codegen/binding-android-arm64': 0.10.2 + '@yuku-codegen/binding-darwin-arm64': 0.10.2 + '@yuku-codegen/binding-darwin-x64': 0.10.2 + '@yuku-codegen/binding-freebsd-x64': 0.10.2 + '@yuku-codegen/binding-linux-arm-gnu': 0.10.2 + '@yuku-codegen/binding-linux-arm-musl': 0.10.2 + '@yuku-codegen/binding-linux-arm64-gnu': 0.10.2 + '@yuku-codegen/binding-linux-arm64-musl': 0.10.2 + '@yuku-codegen/binding-linux-x64-gnu': 0.10.2 + '@yuku-codegen/binding-linux-x64-musl': 0.10.2 + '@yuku-codegen/binding-win32-arm64': 0.10.2 + '@yuku-codegen/binding-win32-x64': 0.10.2 + + yuku-parser@0.10.2: + dependencies: + '@yuku-toolchain/types': 0.10.2 + yuku-ast: 0.10.2 + optionalDependencies: + '@yuku-parser/binding-android-arm64': 0.10.2 + '@yuku-parser/binding-darwin-arm64': 0.10.2 + '@yuku-parser/binding-darwin-x64': 0.10.2 + '@yuku-parser/binding-freebsd-x64': 0.10.2 + '@yuku-parser/binding-linux-arm-gnu': 0.10.2 + '@yuku-parser/binding-linux-arm-musl': 0.10.2 + '@yuku-parser/binding-linux-arm64-gnu': 0.10.2 + '@yuku-parser/binding-linux-arm64-musl': 0.10.2 + '@yuku-parser/binding-linux-x64-gnu': 0.10.2 + '@yuku-parser/binding-linux-x64-musl': 0.10.2 + '@yuku-parser/binding-win32-arm64': 0.10.2 + '@yuku-parser/binding-win32-x64': 0.10.2 diff --git a/rolldown.config.mjs b/rolldown.config.mjs new file mode 100644 index 0000000..17662cc --- /dev/null +++ b/rolldown.config.mjs @@ -0,0 +1,12 @@ +import { defineConfig } from 'rolldown' +import { dts } from 'rolldown-plugin-dts' + +export default defineConfig({ + input: 'src/index.ts', + plugins: [dts({ emitDtsOnly: true })], + output: { + dir: 'dist', + format: 'es', + entryFileNames: '[name].mjs', + }, +}) diff --git a/scripts/commonjs-types.mjs b/scripts/commonjs-types.mjs new file mode 100644 index 0000000..968bba1 --- /dev/null +++ b/scripts/commonjs-types.mjs @@ -0,0 +1,80 @@ +import { copyFileSync, readFileSync, writeFileSync } from 'node:fs' +import ts from 'typescript' + +copyFileSync('dist/index.d.mts', 'dist/index.d.ts') + +const source = ts.createSourceFile( + 'index.d.ts', + readFileSync('dist/index.d.ts', 'utf8'), + ts.ScriptTarget.Latest, + true, +) +const declarations = new Map( + source.statements + .filter((statement) => statement.name) + .map((statement) => [statement.name.text, statement]), +) +const aliases = [] +for (const statement of source.statements) { + if ( + statement.modifiers?.some( + (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword, + ) && + !statement.modifiers.some( + (modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword, + ) + ) { + if ( + ts.isInterfaceDeclaration(statement) || + ts.isTypeAliasDeclaration(statement) + ) { + const parameters = statement.typeParameters + aliases.push( + `export type ${statement.name.text}${parameters?.length ? `<${parameters.map((parameter) => parameter.getText(source)).join(', ')}>` : ''} = API.${statement.name.text}${parameters?.length ? `<${parameters.map((parameter) => parameter.name.text).join(', ')}>` : ''};`, + ) + } else if (statement.name) { + aliases.push( + `export import ${statement.name.text} = API.${statement.name.text};`, + ) + } else if (ts.isVariableStatement(statement)) { + for (const declaration of statement.declarationList.declarations) { + aliases.push( + `export import ${declaration.name.getText(source)} = API.${declaration.name.getText(source)};`, + ) + } + } + } + if ( + !ts.isExportDeclaration(statement) || + !statement.exportClause || + !ts.isNamedExports(statement.exportClause) + ) + continue + for (const element of statement.exportClause.elements) { + if (element.name.text === 'default') continue + if (!statement.isTypeOnly && !element.isTypeOnly) { + aliases.push( + `export import ${element.name.text} = API.${element.name.text};`, + ) + continue + } + const parameters = declarations.get( + (element.propertyName || element.name).text, + )?.typeParameters + aliases.push( + `export type ${element.name.text}${parameters?.length ? `<${parameters.map((parameter) => parameter.getText(source)).join(', ')}>` : ''} = API.${element.name.text}${parameters?.length ? `<${parameters.map((parameter) => parameter.name.text).join(', ')}>` : ''};`, + ) + } +} +writeFileSync( + 'dist/index.d.cts', + `import * as API from './index.js'; +declare class Facturapi extends API.default { + static readonly default: typeof Facturapi; +} +declare namespace Facturapi { +${aliases.join('\n')} +} +export = Facturapi; +`, +) diff --git a/scripts/generate-sdk.mjs b/scripts/generate-sdk.mjs new file mode 100644 index 0000000..21d3f2f --- /dev/null +++ b/scripts/generate-sdk.mjs @@ -0,0 +1,434 @@ +import assert from 'node:assert/strict' +import { readFile, writeFile, mkdir } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' +import openapiTS, { astToString } from 'openapi-typescript' +import ts from 'typescript' +import prettier from 'prettier' +import { compileDatePlans } from './sdk/date-plans.mjs' +import { resolveOperationBinding } from './sdk/operation-bindings.mjs' +import { readSpecification } from './sdk/openapi-source.mjs' +import { methodDocumentation } from './sdk/documentation.mjs' + +const root = new URL('../', import.meta.url) +const spec = await readSpecification( + JSON.parse(await readFile(new URL('openapi/source.json', root), 'utf8')), +) +const resources = JSON.parse( + await readFile(new URL('scripts/sdk/resources.json', root), 'utf8'), +) +const banner = '// Generated by pnpm generate:sdk. Do not edit directly.\n' +const outputs = new Map() +const operations = new Map() +for (const [path, item] of Object.entries(spec.paths)) + for (const [method, operation] of Object.entries(item)) { + if (!operation.operationId) continue + assert( + !operations.has(operation.operationId), + `Duplicate operation: ${operation.operationId}`, + ) + operations.set(operation.operationId, { ...operation, path, method }) + } +const enumSources = ['src/enums.ts', 'src/types/webhook.ts'] +const enumBindings = JSON.parse( + await readFile(new URL('scripts/sdk/enums.json', root), 'utf8'), +) +const enums = [] +for (const filename of enumSources) { + const source = ts.createSourceFile( + filename, + await readFile(new URL(filename, root), 'utf8'), + ts.ScriptTarget.Latest, + true, + ) + for (const node of source.statements.filter(ts.isEnumDeclaration)) { + const values = node.members.map((member) => + member.initializer && ts.isStringLiteralLike(member.initializer) + ? member.initializer.text + : null, + ) + if (values.every((value) => value !== null)) + enums.push({ + name: node.name.text, + values, + filename: filename.replace('src/', '../').replace('.ts', ''), + }) + } +} +for (const [pointer, name] of Object.entries(enumBindings)) { + const schema = pointer + .slice(2) + .split('/') + .reduce( + (value, key) => value?.[key.replaceAll('~1', '/').replaceAll('~0', '~')], + spec, + ) + const enumeration = enums.find((enumeration) => enumeration.name === name) + assert( + schema?.enum && + enumeration && + schema.enum.length === enumeration.values.length && + enumeration.values.every((value) => schema.enum.includes(value)), + `Public enum drift at ${pointer}. Update its named SDK enum.`, + ) + // A generation-only annotation keeps semantic aliases independent of the + // transform hook's traversal path (which can omit properties/items/allOf). + schema['x-sdk-enum'] = name +} +for (const mode of ['input', 'output']) { + const imports = new Map() + const directionalSpec = structuredClone(spec) + function omitReadOnly(value) { + if (!value || typeof value !== 'object') return + for (const [key, property] of Object.entries(value.properties || {})) { + if (property.readOnly) { + delete value.properties[key] + if (value.required) + value.required = value.required.filter((name) => name !== key) + } + } + for (const child of Object.values(value)) omitReadOnly(child) + } + if (mode === 'input') omitReadOnly(directionalSpec) + const ast = await openapiTS(directionalSpec, { + defaultNonNullable: false, + emptyObjectsUnknown: true, + transform(schema) { + if (schema.format === 'date-time') { + const types = [ts.factory.createTypeReferenceNode('Date')] + if (mode === 'input') + types.push( + ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + ) + if (Array.isArray(schema.type) && schema.type.includes('null')) + types.push(ts.factory.createLiteralTypeNode(ts.factory.createNull())) + return types.length === 1 + ? types[0] + : ts.factory.createUnionTypeNode(types) + } + if (schema.format === 'binary') { + imports.set( + mode === 'input' ? 'BinaryInput' : 'BinaryDownload', + '../types/runtime', + ) + return ts.factory.createTypeReferenceNode( + mode === 'input' ? 'BinaryInput' : 'BinaryDownload', + ) + } + if (mode === 'output' && schema['x-sdk-enum']) { + const match = enums.find( + (enumeration) => enumeration.name === schema['x-sdk-enum'], + ) + if (match) { + imports.set(match.name, match.filename) + const types = [ts.factory.createTypeReferenceNode(match.name)] + if (Array.isArray(schema.type) && schema.type.includes('null')) + types.push( + ts.factory.createLiteralTypeNode(ts.factory.createNull()), + ) + return types.length === 1 + ? types[0] + : ts.factory.createUnionTypeNode(types) + } + } + }, + }) + outputs.set( + `src/generated/${mode}.ts`, + banner + + [...imports] + .map(([name, file]) => `import type { ${name} } from '${file}';`) + .join('\n') + + '\n' + + // Use prose for descriptions rather than repeated tags in union completions. + astToString(ast).replace(/^(\s*\/\*\*|\s*\*) @description /gm, '$1 '), + ) +} +outputs.set( + 'src/generated/contracts.ts', + banner + + ` +import type { operations as Input } from './input'; +import type { operations as Output } from './output'; +export type OperationId = keyof Input; +type Content = T extends { content: infer C } ? C[keyof C] : never; +export type OperationBody = Content>; +export type OperationQuery = NonNullable; +export type OperationPath = NonNullable; +export type OperationResponse = { + [S in keyof Output[K]['responses']]: S extends number + ? \`\${S}\` extends \`2\${string}\` ? Content : never + : never; +}[keyof Output[K]['responses']]; +`, +) +const used = new Set(['validateWebhookSignature']) +for (const [name, resource] of Object.entries(resources)) { + const imports = [ + `import type { WrapperClient } from '../wrapper';`, + `import type { OperationBody, OperationQuery, OperationResponse } from '../generated/contracts';`, + `import { operationDatePlans } from '../generated/dates';`, + ] + const methods = [] + for (const [methodName, binding] of Object.entries(resource.methods)) { + if (binding.extension === 'validateSignature') { + imports.push( + `import type { ApiEvent, ApiEventPayload, ApiEventType } from '../types';`, + `import { validateSignature } from '../runtime/webhooks';`, + ) + methods.push( + `/** + * Valida la firma del webhook y devuelve el evento con sus fechas como Date. + * Usa criptografía local cuando está disponible; en otros entornos consulta la API. + * @param data - Datos para verificar el evento. + * @param data.secret - Secreto del webhook. + * @param data.signature - Firma recibida en el encabezado Facturapi-Signature. + * @param data.payload - Preferentemente, el cuerpo original como texto o bytes. También acepta un evento como objeto. + * @returns Evento validado, siempre como objeto. + * @throws Si la firma es inválida o el payload no se puede interpretar como JSON. + */ +validateSignature(data: { secret: string; signature: string; payload: string | Uint8Array | ArrayBuffer | ApiEventPayload }): Promise> { return validateSignature(this.client, data); }`, + ) + continue + } + const operationId = + typeof binding === 'string' ? binding : binding.operation + const operation = operations.get(operationId) + assert( + operation, + `Missing operation for ${name}.${methodName}: ${operationId}`, + ) + const entry = { + ...resolveOperationBinding( + spec, + operation, + typeof binding === 'string' ? {} : binding, + ), + name: methodName, + operation: operationId, + } + used.add(entry.operation) + for (const [schema, source] of [ + ['bodySchema', entry.body], + ['querySchema', entry.hasQuery], + ]) { + if (!entry[schema]) continue + assert( + spec.components.schemas[entry[schema]], + `Missing ${schema} schema.`, + ) + assert(source, `${schema} requires its HTTP argument.`) + imports.push( + `import type { components as InputComponents } from '../generated/input';`, + ) + } + const argumentsList = entry.arguments.map((argument) => { + let type = argument.type + const source = + entry.body?.argument === argument.name + ? 'body' + : entry.params?.argument === argument.name + ? 'params' + : null + if (source) + type = + source === 'body' && operation.requestBody + ? `OperationBody<'${entry.operation}'>` + : source === 'params' && entry.hasQuery + ? `OperationQuery<'${entry.operation}'>${argument.nullable ? ' | null' : ''}` + : 'Record | null' + if (source === 'body' && entry.bodySchema) + type = `InputComponents['schemas']['${entry.bodySchema}']` + if (source === 'params' && entry.querySchema) + type = `InputComponents['schemas']['${entry.querySchema}']${argument.nullable ? ' | null' : ''}` + for (const [property, binding] of Object.entries(entry.body || {})) + if (binding?.argument === argument.name) + type = `OperationBody<'${entry.operation}'>[${JSON.stringify(property)}]` + for (const [property, binding] of Object.entries(entry.params || {})) + if (binding?.argument === argument.name) + type = `OperationQuery<'${entry.operation}'>[${JSON.stringify(property)}]` + if (entry.extension) type = argument.type + return `${argument.name}${argument.optional ? '?' : ''}: ${type}` + }) + const path = operation.path.replace(/\{([^}]+)\}/g, (_, key) => { + assert( + entry.path[key], + `Missing path binding: ${name}.${entry.name}.${key}`, + ) + return entry.path[key].argument + ? `\${encodeURIComponent(${entry.path[key].argument})}` + : entry.path[key].value + }) + let setup = '' + if (entry.extension === 'uploadLogo') { + imports.push( + `import type { BinaryInput } from '../types/runtime';`, + `import { prepareFile } from '../runtime/uploads';`, + ) + setup = `const formData = new FormData(); formData.append('file', await prepareFile(file, 'application/octet-stream'), 'file');` + } else if (entry.extension === 'uploadCertificate') { + setup = `const formData = new FormData(); const [cer, key] = await Promise.all([prepareFile(cerFile, 'application/octet-stream'), prepareFile(keyFile, 'application/octet-stream')]); formData.append('cer', cer, 'cer.cer'); formData.append('key', key, 'key.key'); formData.append('password', password);` + } + if (entry.extension) + setup = + `if (typeof FormData === 'undefined') throw new Error('FormData is not available in this runtime. Use Node.js 18+ or provide a FormData implementation.');\n` + + setup + const options = [ + `method: '${operation.method.toUpperCase()}'`, + `datePlan: operationDatePlans.${entry.operation}`, + ] + for (const kind of ['body', 'params']) + if (entry[kind]) + options.push( + `${kind}: ${ + entry[kind].argument || + '{' + + Object.entries(entry[kind]) + .map( + ([property, binding]) => `${property}: ${binding.argument}`, + ) + .join(', ') + + '}' + }`, + ) + if (entry.formData) options.push('formData') + const pathArguments = Object.values(entry.path) + .filter((binding) => binding.argument) + .map((binding) => binding.argument) + const guard = pathArguments + .map( + (argument) => + `if (!${argument}) return Promise.reject(new Error('${argument} is required'));`, + ) + .join('\n') + const documentation = methodDocumentation(spec, operation, entry) + if (entry.bodyByQueryFlag) { + assert( + spec.components.schemas[entry.bodyByQueryFlag.true], + 'Missing conditional body schema.', + ) + assert( + entry.body?.argument && entry.params?.argument, + 'Conditional bodies require body and query arguments.', + ) + imports.push( + `import type { components as InputComponents } from '../generated/input';`, + ) + methods.push( + `${documentation}${entry.name}(${entry.body.argument}: InputComponents['schemas']['${entry.bodyByQueryFlag.true}'], ${entry.params.argument}: OperationQuery<'${entry.operation}'> & { ${entry.bodyByQueryFlag.property}: true }): Promise>;`, + ) + methods.push( + `${documentation}${entry.name}(${argumentsList.join(', ')}): Promise>;`, + ) + argumentsList[ + entry.arguments.findIndex( + (argument) => argument.name === entry.body.argument, + ) + ] = + `${entry.body.argument}: OperationBody<'${entry.operation}'> | InputComponents['schemas']['${entry.bodyByQueryFlag.true}']` + } + if (entry.responseByFlag) { + imports.push( + `import type { components as OutputComponents } from '../generated/output';`, + ) + assert.equal( + entry.arguments.length, + 1, + 'Response flags currently require one body argument.', + ) + for (const flag of ['true', 'false']) { + assert( + spec.components.schemas[entry.responseByFlag[flag]], + 'Missing response variant schema.', + ) + methods.push( + `${documentation}${entry.name}(${entry.responseByFlag.argument}: OperationBody<'${entry.operation}'> & { ${entry.responseByFlag.property}${flag === 'false' ? '?' : ''}: ${flag} }): Promise;`, + ) + } + methods.push( + `${documentation}${entry.name}(${argumentsList.join(', ')}): Promise>;`, + ) + } + methods.push( + `${documentation}${entry.extension ? 'async ' : ''}${entry.name}(${argumentsList.join(', ')}): Promise> { ${guard}\n${setup}\nreturn this.client.request>(\`${path}\`, {${options.join(', ')}}); }`, + ) + } + outputs.set( + `src/${resource.directory}/${name}.ts`, + banner + + [...new Set(imports)].join('\n') + + `\nexport default class ${resource.className} {\nconstructor(public client: WrapperClient) {}\n${methods.join('\n\n')}\n}\n`, + ) +} +const models = JSON.parse( + await readFile(new URL('scripts/sdk/models.json', root), 'utf8'), +) +const aliases = new Set([ + 'ApiEvent', + 'ApiEventData', + 'Webhook', + 'SearchResult', + ...enums.map((enumeration) => enumeration.name), +]) +for (const [file, names] of Object.entries(models)) { + let content = + banner + + "import type { components as InputComponents } from '../generated/input';\nimport type { components as OutputComponents } from '../generated/output';\nimport type { OperationBody, OperationQuery, OperationResponse } from '../generated/contracts';\ntype Input = InputComponents['schemas'];\ntype Output = OutputComponents['schemas'];\n" + for (const [name, expression] of Object.entries(names)) { + aliases.add(name) + content += `export type ${name} = ${expression};\n` + } + if (file === 'common') + content += `export * from './runtime'; +export type SearchResult = Output['SearchResult'] & { data: T[] }; +export type PageSearchParams = ({ pagination?: 'page' } | { page: number }) & Record; +export type CursorSearchParams = ({ pagination: 'cursor' } | { after: string } | { before: string }) & Record; +` + outputs.set(`src/types/${file}.ts`, content) +} +outputs.set( + 'src/generated/models.ts', + banner + + "import type { components as Input } from './input';\nimport type { components as Output } from './output';\n" + + Object.keys(spec.components.schemas) + .filter((name) => !aliases.has(name)) + .map( + (name) => + `export type ${name} = ${name.endsWith('Input') ? 'Input' : 'Output'}['schemas'][${JSON.stringify(name)}];`, + ) + .join('\n') + + '\n', +) +const missing = [...operations.keys()].filter((name) => !used.has(name)) +assert.equal( + missing.length, + 0, + `Unmapped public operations: ${missing.join(', ')}`, +) +// TypeScript resolves all schema references and unions for the Date compiler. +await mkdir(new URL('src/generated/', root), { recursive: true }) +const plans = compileDatePlans( + fileURLToPath(new URL('src/generated/output.ts', root)), + outputs.get('src/generated/output.ts'), +) +outputs.set( + 'src/generated/dates.ts', + banner + + `import type { DatePlan } from '../runtime/dates';\nexport const datePlans: DatePlan[] = ${JSON.stringify(plans.nodes)};\nexport const componentDatePlans = ${JSON.stringify(plans.components)} as const;\nexport const operationDatePlans = ${JSON.stringify(plans.operations)} as const;\n`, +) +for (const [filename, content] of outputs) { + const formatted = await prettier.format(content, { + ...(await prettier.resolveConfig(fileURLToPath(new URL(filename, root)))), + filepath: filename, + }) + if (process.argv.includes('--check')) { + assert( + (await readFile(new URL(filename, root), 'utf8')) === formatted, + `${filename} is stale. Run pnpm generate:sdk.`, + ) + } else { + await writeFile(new URL(filename, root), formatted) + } +} +console.log( + `${process.argv.includes('--check') ? 'Verified' : 'Generated'} ${operations.size} operations and ${Object.keys(spec.components.schemas).length} schemas`, +) diff --git a/scripts/sdk/date-plans.mjs b/scripts/sdk/date-plans.mjs new file mode 100644 index 0000000..6d7497c --- /dev/null +++ b/scripts/sdk/date-plans.mjs @@ -0,0 +1,233 @@ +import ts from 'typescript' + +// Inspect the types produced by openapi-typescript instead of implementing +// JSON Schema reference, intersection, and union resolution a second time. +export function compileDatePlans(filename, content) { + const options = { + strict: true, + target: ts.ScriptTarget.ES2022, + skipLibCheck: true, + } + const host = ts.createCompilerHost(options) + const getSourceFile = host.getSourceFile.bind(host) + host.getSourceFile = (path, languageVersion, ...rest) => + path === filename + ? ts.createSourceFile(path, content, languageVersion, true) + : getSourceFile(path, languageVersion, ...rest) + const program = ts.createProgram([filename], options, host) + const checker = program.getTypeChecker() + const source = program.getSourceFile(filename) + const nodes = [{ kind: 'none' }, { kind: 'date' }] + const visited = new Map() + const literals = (type) => + type.isUnion() + ? type.types.flatMap(literals) + : type.isStringLiteral() || type.isNumberLiteral() + ? [type.value] + : [] + function compile(type) { + if (type.symbol?.name === 'Date') return 1 + if (visited.has(type)) return visited.get(type) + if (type.isUnion()) { + const variants = type.types.filter( + (variant) => + !(variant.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)), + ) + if (variants.length === 1) return compile(variants[0]) + if ( + variants.some((variant) => variant.symbol?.name === 'Date') && + variants.every( + (variant) => + variant.symbol?.name === 'Date' || + variant.flags & ts.TypeFlags.StringLike, + ) + ) { + const id = nodes.length + visited.set(type, id) + nodes.push({ kind: 'date-time' }) + return id + } + } + if ( + type.flags & + (ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.StringLike | + ts.TypeFlags.NumberLike | + ts.TypeFlags.BooleanLike | + ts.TypeFlags.Null | + ts.TypeFlags.Undefined | + ts.TypeFlags.Never) + ) + return 0 + const id = nodes.length + visited.set(type, id) + nodes.push({ kind: 'none' }) + if (type.isUnion()) { + nodes[id] = { + kind: 'union', + variants: type.types.map((variant) => ({ + plan: compile(variant), + match: Object.fromEntries( + checker.getPropertiesOfType(variant).flatMap((property) => { + const values = literals( + checker.getTypeOfSymbolAtLocation(property, source), + ) + return values.length === 1 ? [[property.name, values]] : [] + }), + ), + })), + } + } else if (checker.isArrayType(type) || checker.isTupleType(type)) { + nodes[id] = { + kind: 'array', + items: compile(checker.getIndexTypeOfType(type, ts.IndexKind.Number)), + } + } else { + nodes[id] = { + kind: 'object', + properties: Object.fromEntries( + checker + .getPropertiesOfType(type) + .map((property) => [ + property.name, + compile(checker.getTypeOfSymbolAtLocation(property, source)), + ]), + ), + additional: checker.getIndexTypeOfType(type, ts.IndexKind.String) + ? compile(checker.getIndexTypeOfType(type, ts.IndexKind.String)) + : 0, + } + } + return id + } + const components = checker.getTypeAtLocation( + source.statements.find( + (node) => + ts.isInterfaceDeclaration(node) && node.name.text === 'components', + ), + ) + const schemas = checker.getTypeOfSymbolAtLocation( + checker.getPropertyOfType(components, 'schemas'), + source, + ) + const componentPlans = Object.fromEntries( + checker + .getPropertiesOfType(schemas) + .map((property) => [ + property.name, + compile(checker.getTypeOfSymbolAtLocation(property, source)), + ]), + ) + const operations = checker.getTypeAtLocation( + source.statements.find( + (node) => + ts.isInterfaceDeclaration(node) && node.name.text === 'operations', + ), + ) + const operationPlans = Object.fromEntries( + checker.getPropertiesOfType(operations).map((property) => { + const operation = checker.getTypeOfSymbolAtLocation(property, source) + const responses = checker.getTypeOfSymbolAtLocation( + checker.getPropertyOfType(operation, 'responses'), + source, + ) + const plans = checker + .getPropertiesOfType(responses) + .filter((response) => /^2\d\d$/.test(response.name)) + .flatMap((response) => { + const content = checker.getPropertyOfType( + checker.getTypeOfSymbolAtLocation(response, source), + 'content', + ) + if (!content) return [] + const json = checker.getPropertyOfType( + checker.getNonNullableType( + checker.getTypeOfSymbolAtLocation(content, source), + ), + 'application/json', + ) + return json + ? [compile(checker.getTypeOfSymbolAtLocation(json, source))] + : [] + }) + const id = + plans.length === 1 + ? plans[0] + : nodes.push({ + kind: 'union', + variants: plans.map((plan) => ({ plan, match: {} })), + }) - 1 + return [property.name, id] + }), + ) + // Retain only branches that can reach a Date, including recursive types. + const active = new Set( + nodes.flatMap((node, id) => + node.kind === 'date' || node.kind === 'date-time' ? [id] : [], + ), + ) + for (let changed = true; changed;) { + changed = false + nodes.forEach((node, id) => { + const children = + node.kind === 'object' + ? [...Object.values(node.properties), node.additional] + : node.kind === 'array' + ? [node.items] + : node.kind === 'union' + ? node.variants.map((variant) => variant.plan) + : [] + if (!active.has(id) && children.some((child) => active.has(child))) { + active.add(id) + changed = true + } + }) + } + const ids = new Map( + [...active].sort((a, b) => a - b).map((id, index) => [id, index + 1]), + ) + return { + nodes: [ + { kind: 'none' }, + ...[...ids.keys()].map((id) => { + const node = nodes[id] + if (node.kind === 'object') + return { + kind: 'object', + properties: Object.fromEntries( + Object.entries(node.properties) + .filter(([, plan]) => active.has(plan)) + .map(([name, plan]) => [name, ids.get(plan)]), + ), + ...(active.has(node.additional) + ? { additional: ids.get(node.additional) } + : {}), + } + if (node.kind === 'array') + return { ...node, items: ids.get(node.items) } + if (node.kind === 'union') + return { + ...node, + variants: node.variants.map((variant) => ({ + ...variant, + plan: ids.get(variant.plan) || 0, + })), + } + return node + }), + ], + components: Object.fromEntries( + Object.entries(componentPlans).map(([name, id]) => [ + name, + ids.get(id) || 0, + ]), + ), + operations: Object.fromEntries( + Object.entries(operationPlans).map(([name, id]) => [ + name, + ids.get(id) || 0, + ]), + ), + } +} diff --git a/scripts/sdk/documentation.mjs b/scripts/sdk/documentation.mjs new file mode 100644 index 0000000..b3c3c5b --- /dev/null +++ b/scripts/sdk/documentation.mjs @@ -0,0 +1,122 @@ +// API prose comes from the spec; these notes describe SDK argument/return shapes. +export function methodDocumentation(spec, operation, entry) { + const dereference = (value) => + value?.$ref + ? value.$ref + .slice(2) + .split('/') + .reduce( + (target, part) => + target?.[part.replaceAll('~1', '/').replaceAll('~0', '~')], + spec, + ) + : value + const parameters = [ + ...(spec.paths[operation.path].parameters || []), + ...(operation.parameters || []), + ].map(dereference) + const body = dereference(operation.requestBody) + const bodySchema = dereference(Object.values(body?.content || {})[0]?.schema) + const prose = [ + operation.summary, + entry.bodySchema && spec.components.schemas[entry.bodySchema].description, + operation.description, + entry.bodySchema && + 'Este método conserva los campos requeridos de su variante. Para crear un cliente con datos incompletos, usa create(data, { createEditLink: true }).', + ] + .filter(Boolean) + .map((text) => text.trim()) + const lines = [] + for (const argument of entry.arguments) { + const path = Object.entries(entry.path).find( + ([, binding]) => binding.argument === argument.name, + ) + const field = Object.entries(entry.params || {}).find( + ([, binding]) => binding?.argument === argument.name, + ) + const parameter = parameters.find( + (parameter) => + (path && parameter.in === 'path' && parameter.name === path[0]) || + (field && parameter.in === 'query' && parameter.name === field[0]), + ) + const uploadField = { + file: 'file', + cerFile: 'cer', + keyFile: 'key', + password: 'password', + }[argument.name] + const description = + parameter?.description || + (entry.body?.argument === argument.name + ? body?.description || 'Datos de la solicitud.' + : entry.params?.argument === argument.name + ? 'Parámetros de consulta.' + : dereference(bodySchema?.properties?.[uploadField])?.description || + argument.name) + lines.push(`@param ${argument.name} - ${description}`) + if (entry.params?.argument === argument.name) + for (const parameter of parameters.filter( + (parameter) => + parameter.in === 'query' && + (parameter.required || + entry.querySchema || + entry.bodyByQueryFlag?.property === parameter.name) && + parameter.description, + )) + lines.push( + `@param ${argument.name}.${parameter.name} - ${parameter.description}`, + ) + if ( + ['file', 'cerFile', 'keyFile'].includes(argument.name) && + entry.extension + ) + lines.push( + `Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js.`, + ) + } + const responses = Object.entries(operation.responses || {}) + .filter(([status]) => /^2\d\d$/.test(status)) + .map(([status, response]) => ({ status, ...dereference(response) })) + const binary = responses.some((response) => + Object.values(response.content || {}).some( + (content) => dereference(content.schema)?.format === 'binary', + ), + ) + const signedDownload = responses.some((response) => + Object.values(response.content || {}).some( + (content) => + content.schema?.$ref === '#/components/schemas/SignedDownloadUrl', + ), + ) + lines.push( + `@returns ${ + binary + ? 'Archivo como stream en Node.js o Blob en el navegador.' + : signedDownload + ? 'Objeto SignedDownloadUrl con url, expires_at, content_type y filename.' + : responses + .filter((response) => response.description) + .map((response) => + responses.length > 1 + ? `${response.status}: ${response.description}` + : response.description, + ) + .join('\n') + }`, + ) + return ( + '/**\n' + + [...prose, lines.join('\n')] + .join('\n\n') + .replace( + /\]\((\/[^)]*|#[^)]*)\)/g, + (_, link) => + `](${link.startsWith('#') ? 'https://docs.facturapi.io/api/' : 'https://docs.facturapi.io'}${link})`, + ) + .replaceAll('*/', '* /') + .split('\n') + .map((line) => ` * ${line}`) + .join('\n') + + '\n */\n' + ) +} diff --git a/scripts/sdk/enums.json b/scripts/sdk/enums.json new file mode 100644 index 0000000..5b82988 --- /dev/null +++ b/scripts/sdk/enums.json @@ -0,0 +1,33 @@ +{ + "#/components/schemas/IssuingType": "IssuingType", + "#/components/schemas/LocalTax/properties/factor": "TaxFactor", + "#/components/schemas/BaseTax/properties/type": "TaxType", + "#/components/schemas/BaseTax/properties/factor": "TaxFactor", + "#/components/schemas/WebhookProperties/properties/status": "WebhookEndpointStatus", + "#/components/schemas/WebhookCreateInput/allOf/0/properties/enabled_events/items": "ApiEventType", + "#/components/schemas/WebhookCreateEdit/allOf/0/properties/status": "WebhookEndpointStatus", + "#/components/schemas/WebhookCreateEdit/allOf/0/properties/enabled_events/items": "ApiEventType", + "#/components/schemas/PaymentInput/properties/related_documents/items/properties/taxes/items/properties/type": "TaxType", + "#/components/schemas/PaymentInput/properties/related_documents/items/properties/taxes/items/properties/factor": "TaxFactor", + "#/components/schemas/InvoiceZipRequestInvoiceType": "InvoiceType", + "#/components/schemas/InvoiceProperties/properties/status": "InvoiceStatus", + "#/components/schemas/InvoiceProperties/properties/cancellation_status": "CancellationStatus", + "#/components/schemas/InvoiceProperties/properties/type": "InvoiceType", + "#/components/schemas/InvoiceProperties/properties/payment_method": "PaymentMethod", + "#/components/schemas/InvoiceProperties/properties/global/properties/periodicity": "GlobalInvoicePeriodicity", + "#/components/schemas/InvoiceDraftProperties/properties/cancellation_status": "CancellationStatus", + "#/components/schemas/InvoiceDraftProperties/properties/type": "InvoiceType", + "#/components/schemas/InvoiceIngresoInput/allOf/0/properties/payment_method": "PaymentMethod", + "#/components/schemas/InvoiceIngresoInput/allOf/0/properties/global/properties/periodicity": "GlobalInvoicePeriodicity", + "#/components/schemas/InvoiceIngresoEditInput/allOf/0/properties/payment_method": "PaymentMethod", + "#/components/schemas/InvoiceIngresoEditInput/allOf/0/properties/global/properties/periodicity": "GlobalInvoicePeriodicity", + "#/components/schemas/ReceiptProperties/allOf/0/properties/status": "ReceiptStatus", + "#/components/schemas/GlobalInvoiceInputProperties/properties/periodicity": "GlobalInvoicePeriodicity", + "#/components/schemas/Organization/properties/receipts/properties/periodicity": "InvoicingPeriod", + "#/components/schemas/OrganizationReceiptsInput/properties/periodicity": "InvoicingPeriod", + "#/components/schemas/OrganizationSeriesDefaultInput/properties/type": "InvoiceType", + "#/components/schemas/ReceiptInvoiceSummaryTax/properties/factor": "TaxFactor", + "#/components/schemas/IepsMode": "IepsMode", + "#/paths/~1invoices~1{invoice_id}~1payment-summary/get/responses/200/content/application~1json/schema/properties/taxes/items/properties/type": "TaxType", + "#/paths/~1invoices~1{invoice_id}~1payment-summary/get/responses/200/content/application~1json/schema/properties/taxes/items/properties/factor": "TaxFactor" +} diff --git a/scripts/sdk/models.json b/scripts/sdk/models.json new file mode 100644 index 0000000..8bf7605 --- /dev/null +++ b/scripts/sdk/models.json @@ -0,0 +1,66 @@ +{ + "common": { + "Address": "Output['CommonAddressProperties']", + "InvoiceItemPart": "Output['Parts']", + "InvoiceItemThirdParty": "Output['ThirdParty']", + "Tax": "Output['BaseTax'] | Output['IepsTax']", + "LocalTax": "Output['LocalTax']", + "ProductInfo": "Output['LineItemProduct']", + "CustomerInfo": "Output['CustomerInfo']", + "InvoiceItem": "Output['LineItem']", + "XmlNamespace": "Output['NamespaceProperties']", + "RelatedDocument": "Output['RelatedDocument']", + "GenericResponse": "Output['OkResponse']", + "SendEmailBody": "OperationBody<'sendInvoiceByEmail'>", + "SignedDownloadUrl": "Output['SignedDownloadUrl']" + }, + "customer": { + "TaxInfoValidation": "OperationResponse<'validateCustomerTaxInfo'>", + "TaxInfoValidationError": "TaxInfoValidation['errors'][number]", + "Customer": "Output['Customer']" + }, + "product": { + "Product": "Output['Product']" + }, + "invoice": { + "GlobalInfo": "NonNullable", + "InvoiceComplement": "NonNullable[number]", + "Invoice": "Output['Invoice']", + "CancelInvoiceOptions": "Input['CancellationQueryInput']", + "CreateZipRequestData": "OperationBody<'createInvoiceZipRequest'>", + "ListZipRequestsParams": "OperationQuery<'listInvoiceZipRequests'>", + "ZipRequest": "Output['InvoiceZipRequest']", + "PaymentSummaryParams": "OperationQuery<'getInvoicePaymentSummary'>", + "PaymentSummary": "OperationResponse<'getInvoicePaymentSummary'>", + "PaymentSummaryTax": "NonNullable[number]" + }, + "organization": { + "Series": "Output['OrganizationSeriesGroup']", + "OrganizationDefaultSeriesUpdateInput": "Input['OrganizationSeriesDefaultInput']", + "ApiKeys": "OperationResponse<'listLiveApiKeys'>[number]", + "OrganizationUserAccess": "Output['OrganizationUserAccess']", + "OrganizationInvite": "Output['OrganizationInvite']", + "OrganizationInviteCreateInput": "Input['OrganizationInviteCreateInput']", + "OrganizationInviteResponseInput": "Input['OrganizationInviteRespondInput']", + "OrganizationTeamRole": "Output['OrganizationPermissionRole']", + "OrganizationTeamRoleCreateInput": "Input['OrganizationPermissionRoleCreateInput']", + "OrganizationTeamRoleUpdateInput": "Input['OrganizationPermissionRoleUpdateInput']", + "OrganizationTeamRoleTemplate": "Output['OrganizationPermissionRoleTemplate']", + "Organization": "Output['Organization']" + }, + "receipt": { + "Receipt": "Output['Receipt']", + "ReceiptsToInvoiceInput": "Input['ToInvoiceInput']", + "PreviewReceiptsToInvoicePdfInput": "Input['ToInvoicePreviewInput']" + }, + "retention": { + "Retention": "Output['Retention']" + }, + "complements": { + "PagoComplementData": "Output['PaymentProperties']", + "PaymentRelatedDocument": "NonNullable[number]", + "PaymentRelatedDocumentTax": "NonNullable[number]", + "NominaReceptor": "Output['NominaReceptorProperties']", + "NominaComplementData": "Output['NominaComplementDataProperties']" + } +} diff --git a/scripts/sdk/openapi-source.mjs b/scripts/sdk/openapi-source.mjs new file mode 100644 index 0000000..b082a01 --- /dev/null +++ b/scripts/sdk/openapi-source.mjs @@ -0,0 +1,77 @@ +import assert from 'node:assert/strict' +import * as yaml from 'js-yaml' + +export async function resolveRevision(repository, ref = 'main') { + if (/^[a-f0-9]{40}$/.test(ref)) return ref + const response = await fetch( + `https://api.github.com/repos/${repository}/commits/${encodeURIComponent(ref)}`, + { + headers: { Accept: 'application/vnd.github+json' }, + signal: AbortSignal.timeout(30_000), + }, + ) + assert( + response.ok, + `Could not resolve the public documentation ref: HTTP ${response.status}`, + ) + const { sha } = await response.json() + assert.match( + sha, + /^[a-f0-9]{40}$/, + 'Expected a complete documentation commit SHA.', + ) + return sha +} + +export async function readSpecification(source) { + assert.match( + source.revision, + /^[a-f0-9]{40}$/, + 'Pin a complete documentation commit SHA with pnpm sync:openapi.', + ) + const response = await fetch( + `https://raw.githubusercontent.com/${source.repository}/${source.revision}/${source.path}`, + { signal: AbortSignal.timeout(30_000) }, + ) + assert( + response.ok, + `Could not read the public specification: HTTP ${response.status}`, + ) + const content = Buffer.from(await response.arrayBuffer()) + const spec = yaml.load(content.toString('utf8')) + assert(spec.openapi === '3.1.0', 'Expected the public OpenAPI 3.1 contract.') + const presentation = new Set([ + 'x-codeSamples', + 'x-logo', + 'example', + 'examples', + 'externalDocs', + ]) + // Annotation names can also be real property/parameter/schema names. + const dictionaries = new WeakSet() + const dictionaryKeys = new Set([ + 'properties', + 'patternProperties', + '$defs', + 'schemas', + 'parameters', + 'headers', + 'paths', + 'webhooks', + 'responses', + 'content', + 'securitySchemes', + 'requestBodies', + 'callbacks', + 'links', + ]) + return JSON.parse( + JSON.stringify(spec, function (key, value) { + if (value && typeof value === 'object' && dictionaryKeys.has(key)) + dictionaries.add(value) + return presentation.has(key) && !dictionaries.has(this) + ? undefined + : value + }), + ) +} diff --git a/scripts/sdk/operation-bindings.mjs b/scripts/sdk/operation-bindings.mjs new file mode 100644 index 0000000..486e2e3 --- /dev/null +++ b/scripts/sdk/operation-bindings.mjs @@ -0,0 +1,99 @@ +import assert from 'node:assert/strict' + +// The spec owns HTTP bindings. Overrides only preserve SDK naming and signatures. +export function resolveOperationBinding(spec, operation, overrides = {}) { + const parameters = [ + ...(spec.paths[operation.path].parameters || []), + ...(operation.parameters || []), + ].map((parameter) => + parameter.$ref + ? spec.components.parameters[parameter.$ref.split('/').at(-1)] + : parameter, + ) + const pathParameters = [...operation.path.matchAll(/\{([^}]+)\}/g)] + .map(([, name]) => name) + .filter((name) => !(name in (overrides.path || {}))) + for (const name of Object.keys(overrides.path || {})) { + assert( + operation.path.includes(`{${name}}`), + `Unknown path override for ${operation.operationId}: ${name}`, + ) + } + const path = Object.fromEntries( + [...operation.path.matchAll(/\{([^}]+)\}/g)].map(([, name]) => [ + name, + name in (overrides.path || {}) + ? { value: overrides.path[name] } + : { + argument: + overrides.argumentNames?.[name] || + (pathParameters.length === 1 + ? 'id' + : name.replace(/_([a-z])/g, (_, letter) => + letter.toUpperCase(), + )), + }, + ]), + ) + const query = parameters.filter((parameter) => parameter.in === 'query') + const body = + overrides.body || + (operation.requestBody && !overrides.extension + ? { argument: overrides.argumentNames?.body || 'data' } + : undefined) + const params = + overrides.params || + (query.length + ? { argument: overrides.argumentNames?.query || 'params' } + : undefined) + const args = overrides.arguments || [ + ...pathParameters.map((name) => { + assert( + parameters.some( + (parameter) => + parameter.in === 'path' && + parameter.name === name && + parameter.schema?.type === 'string', + ), + `A non-string path parameter needs an explicit SDK argument: ${name}`, + ) + return { name: path[name].argument, optional: false, type: 'string' } + }), + ...(body + ? [ + { + name: body.argument, + optional: operation.requestBody.required === false, + }, + ] + : []), + ...(params + ? [ + { + name: params.argument, + optional: !query.some((parameter) => parameter.required), + nullable: !query.some((parameter) => parameter.required), + }, + ] + : []), + ] + return { + ...overrides, + hasQuery: query.length > 0, + path, + arguments: args.map((argument) => ({ + ...argument, + ...(argument.name in (overrides.optional || {}) + ? { optional: overrides.optional[argument.name] } + : {}), + ...(argument.name in (overrides.nullable || {}) + ? { nullable: overrides.nullable[argument.name] } + : {}), + })), + ...(body ? { body } : {}), + ...(params ? { params } : {}), + ...(overrides.extension && overrides.extension !== 'validateSignature' + ? { formData: true } + : {}), + } +} diff --git a/scripts/sdk/resources.json b/scripts/sdk/resources.json new file mode 100644 index 0000000..f943d4f --- /dev/null +++ b/scripts/sdk/resources.json @@ -0,0 +1,588 @@ +{ + "customers": { + "className": "Customers", + "directory": "resources", + "methods": { + "create": { + "operation": "createCustomer", + "bodyByQueryFlag": { + "property": "createEditLink", + "true": "CustomerCreateWithEditLinkInput" + } + }, + "createNational": { + "operation": "createCustomer", + "bodySchema": "CustomerNationalCreateInput" + }, + "createForeign": { + "operation": "createCustomer", + "bodySchema": "CustomerForeignCreateInput" + }, + "createGeneric": { + "operation": "createCustomer", + "bodySchema": "CustomerGenericCreateInput" + }, + "list": "listCustomers", + "retrieve": "getCustomer", + "update": "editCustomer", + "del": "deleteCustomer", + "validateTaxInfo": "validateCustomerTaxInfo", + "sendEditLinkByEmail": { + "operation": "sendEditLinkByEmail", + "argumentNames": { + "body": "options" + }, + "optional": { + "options": false + } + } + } + }, + "invoices": { + "className": "Invoices", + "directory": "resources", + "methods": { + "create": { + "operation": "createInvoice", + "argumentNames": { + "body": "body" + } + }, + "list": "listInvoices", + "retrieve": "getInvoice", + "paymentSummary": "getInvoicePaymentSummary", + "cancel": { + "operation": "cancelInvoice", + "querySchema": "CancellationQueryInput" + }, + "sendByEmail": { + "operation": "sendInvoiceByEmail", + "argumentNames": { + "body": "options" + } + }, + "downloadPdf": { + "operation": "downloadInvoice", + "path": { + "format": "pdf" + } + }, + "downloadXml": { + "operation": "downloadInvoice", + "path": { + "format": "xml" + } + }, + "downloadZip": { + "operation": "downloadInvoice", + "path": { + "format": "zip" + } + }, + "downloadPdfUrl": { + "operation": "getInvoiceDownloadUrl", + "path": { + "format": "pdf" + } + }, + "downloadXmlUrl": { + "operation": "getInvoiceDownloadUrl", + "path": { + "format": "xml" + } + }, + "downloadZipUrl": { + "operation": "getInvoiceDownloadUrl", + "path": { + "format": "zip" + } + }, + "createZipRequest": "createInvoiceZipRequest", + "listZipRequests": "listInvoiceZipRequests", + "retrieveZipRequest": "retrieveInvoiceZipRequest", + "downloadZipRequest": "downloadInvoiceZipRequest", + "downloadZipRequestUrl": "getInvoiceZipRequestDownloadUrl", + "downloadCancellationReceiptXml": { + "operation": "downloadCancellationReceiptXml", + "path": { + "format": "xml" + } + }, + "downloadCancellationReceiptPdf": { + "operation": "downloadCancellationReceiptXml", + "path": { + "format": "pdf" + } + }, + "downloadCancellationReceiptPdfUrl": { + "operation": "getCancellationReceiptDownloadUrl", + "path": { + "format": "pdf" + } + }, + "downloadCancellationReceiptXmlUrl": { + "operation": "getCancellationReceiptDownloadUrl", + "path": { + "format": "xml" + } + }, + "updateDraft": "updateDraftInvoice", + "stampDraft": "stampDraftInvoice", + "updateStatus": "updateInvoiceStatus", + "copyToDraft": "copyToDraftInvoice", + "previewPdf": { + "operation": "previewInvoicePdf", + "argumentNames": { + "body": "body" + } + }, + "previewPdfUrl": { + "operation": "previewInvoicePdfUrl", + "argumentNames": { + "body": "body" + } + } + } + }, + "organizations": { + "className": "Organizations", + "directory": "resources", + "methods": { + "create": "createOrganization", + "list": "listOrganizations", + "retrieve": "getOrganization", + "updateLegal": "editOrganizationLegal", + "updateCustomization": "editOrganizationCustomization", + "updateReceiptSettings": "editOrganizationReceiptsSettings", + "updateDomain": "editOrganizationDomain", + "checkDomainIsAvailable": { + "operation": "checkDomainAvailability", + "argumentNames": { + "query": "data" + } + }, + "uploadLogo": { + "operation": "uploadOrganizationLogo", + "extension": "uploadLogo", + "arguments": [ + { + "name": "id", + "optional": false, + "type": "string" + }, + { + "name": "file", + "optional": false, + "type": "BinaryInput" + } + ] + }, + "uploadCertificate": { + "operation": "uploadOrganizationCertificate", + "extension": "uploadCertificate", + "arguments": [ + { + "name": "id", + "optional": false, + "type": "string" + }, + { + "name": "cerFile", + "optional": false, + "type": "BinaryInput" + }, + { + "name": "keyFile", + "optional": false, + "type": "BinaryInput" + }, + { + "name": "password", + "optional": false, + "type": "string" + } + ] + }, + "deleteCertificate": "deleteOrganizationCertificate", + "del": "deleteOrganization", + "getTestApiKey": "getTestApiKey", + "renewTestApiKey": "renewTestApiKey", + "listLiveApiKeys": "listLiveApiKeys", + "renewLiveApiKey": "renewLiveApiKey", + "deleteLiveApiKey": { + "operation": "deleteLiveApiKey", + "argumentNames": { + "id": "apiKeyId" + } + }, + "listSeriesGroup": { + "operation": "getSeriesGroup", + "argumentNames": { + "organization_id": "organization_id" + } + }, + "createSeriesGroup": { + "operation": "createSeriesGroup", + "argumentNames": { + "organization_id": "organization_id", + "body": "seriesData" + } + }, + "updateSeriesGroup": { + "operation": "updateSeriesGroup", + "argumentNames": { + "organization_id": "organization_id" + } + }, + "updateDefaultSeries": { + "operation": "updateDefaultSeries", + "argumentNames": { + "organization_id": "organization_id" + } + }, + "deleteSeriesGroup": { + "operation": "deleteSeriesGroup", + "argumentNames": { + "organization_id": "organization_id" + } + }, + "me": "meOrganization", + "updateSelfInvoiceSettings": "editOrganizationSelfInvoiceSettings", + "listTeamAccess": { + "operation": "getOrganizationTeam", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "retrieveTeamAccess": "getOrganizationTeamUser", + "updateTeamAccessRole": { + "operation": "updateOrganizationTeamUserRole", + "body": { + "role": { + "argument": "role" + } + }, + "arguments": [ + { + "name": "organizationId", + "optional": false, + "type": "string" + }, + { + "name": "accessId", + "optional": false, + "type": "string" + }, + { + "name": "role", + "optional": false, + "type": "string" + } + ] + }, + "removeTeamAccess": "removeOrganizationUserAccess", + "listSentTeamInvites": { + "operation": "listOrganizationTeamInvites", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "inviteUserToTeam": { + "operation": "createOrganizationTeamInvite", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "cancelTeamInvite": "deleteOrganizationTeamInvite", + "listReceivedTeamInvites": "listPendingOrganizationInvites", + "respondTeamInvite": { + "operation": "respondOrganizationInvite", + "argumentNames": { + "invite_key": "inviteKey" + } + }, + "listTeamRoles": { + "operation": "listOrganizationPermissionRoles", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "listTeamRoleTemplates": { + "operation": "listOrganizationPermissionRoleTemplates", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "listTeamRoleOperations": { + "operation": "listOrganizationPermissionOperations", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "retrieveTeamRole": "getOrganizationPermissionRole", + "createTeamRole": { + "operation": "createOrganizationPermissionRole", + "argumentNames": { + "organization_id": "organizationId" + } + }, + "updateTeamRole": "updateOrganizationPermissionRole", + "deleteTeamRole": "deleteOrganizationPermissionRole", + "uploadFiel": { + "operation": "uploadOrganizationFiel", + "extension": "uploadCertificate", + "arguments": [ + { + "name": "id", + "optional": false, + "type": "string" + }, + { + "name": "cerFile", + "optional": false, + "type": "BinaryInput" + }, + { + "name": "keyFile", + "optional": false, + "type": "BinaryInput" + }, + { + "name": "password", + "optional": false, + "type": "string" + } + ] + } + } + }, + "products": { + "className": "Products", + "directory": "resources", + "methods": { + "create": "createProduct", + "list": "listProducts", + "retrieve": "getProduct", + "update": "editProduct", + "del": "deleteProduct" + } + }, + "receipts": { + "className": "Receipts", + "directory": "resources", + "methods": { + "create": "createReceipt", + "list": "listReceipts", + "retrieve": "getReceipt", + "invoice": "invoiceReceipt", + "createGlobalInvoice": "createGlobalInvoice", + "toInvoice": { + "operation": "createToInvoiceFromReceipts", + "responseByFlag": { + "argument": "data", + "property": "dry_run", + "true": "ToInvoiceSummary", + "false": "Invoice" + } + }, + "previewToInvoicePdf": "previewToInvoiceFromReceipts", + "previewToInvoicePdfUrl": "previewToInvoiceFromReceiptsUrl", + "cancel": "cancelReceipt", + "sendByEmail": "sendReceiptByEmail", + "downloadPdf": "downloadReceiptPdf", + "downloadPdfUrl": "getReceiptDownloadUrl", + "updateCustomer": "assignReceiptCustomer" + } + }, + "retentions": { + "className": "Retentions", + "directory": "resources", + "methods": { + "create": "createRetention", + "list": "listRetentions", + "retrieve": "getRetention", + "cancel": { + "operation": "cancelRetention", + "querySchema": "CancellationQueryInput", + "nullable": { + "params": false + } + }, + "updateDraft": "updateDraftRetention", + "stampDraft": "stampDraftRetention", + "copyToDraft": "copyToDraftRetention", + "sendByEmail": "sendRetentionByEmail", + "downloadPdf": { + "operation": "downloadRetention", + "path": { + "format": "pdf" + } + }, + "downloadXml": { + "operation": "downloadRetention", + "path": { + "format": "xml" + } + }, + "downloadZip": { + "operation": "downloadRetention", + "path": { + "format": "zip" + } + }, + "downloadPdfUrl": { + "operation": "getRetentionDownloadUrl", + "path": { + "format": "pdf" + } + }, + "downloadXmlUrl": { + "operation": "getRetentionDownloadUrl", + "path": { + "format": "xml" + } + }, + "downloadZipUrl": { + "operation": "getRetentionDownloadUrl", + "path": { + "format": "zip" + } + } + } + }, + "cartaPorteCatalogs": { + "className": "CartaPorteCatalogs", + "directory": "tools", + "methods": { + "searchAirTransportCodes": { + "operation": "searchCartaPorteAirTransportCodes", + "nullable": { + "params": true + } + }, + "searchTransportConfigs": { + "operation": "searchCartaPorteTransportConfigs", + "nullable": { + "params": true + } + }, + "searchRightsOfPassage": { + "operation": "searchCartaPorteRightsOfPassage", + "nullable": { + "params": true + } + }, + "searchCustomsDocuments": { + "operation": "searchCartaPorteCustomsDocuments", + "nullable": { + "params": true + } + }, + "searchPackagingTypes": { + "operation": "searchCartaPortePackagingTypes", + "nullable": { + "params": true + } + }, + "searchTrailerTypes": { + "operation": "searchCartaPorteTrailerTypes", + "nullable": { + "params": true + } + }, + "searchHazardousMaterials": { + "operation": "searchCartaPorteHazardousMaterials", + "nullable": { + "params": true + } + }, + "searchNavalAuthorizations": { + "operation": "searchCartaPorteNavalAuthorizations", + "nullable": { + "params": true + } + }, + "searchPortStations": { + "operation": "searchCartaPortePortStations", + "nullable": { + "params": true + } + }, + "searchMarineContainers": { + "operation": "searchCartaPorteMarineContainers", + "nullable": { + "params": true + } + } + } + }, + "catalogs": { + "className": "Catalogs", + "directory": "tools", + "methods": { + "searchProducts": { + "operation": "searchProducts", + "optional": { + "params": false + } + }, + "searchUnits": { + "operation": "searchUnits", + "optional": { + "params": false + } + } + } + }, + "comercioExteriorCatalogs": { + "className": "ComercioExteriorCatalogs", + "directory": "tools", + "methods": { + "searchTariffFractions": "searchComercioExteriorTariffFractions" + } + }, + "tools": { + "className": "Tools", + "directory": "tools", + "methods": { + "validateTaxId": { + "operation": "validateTaxId", + "params": { + "tax_id": { + "argument": "taxId" + } + }, + "arguments": [ + { + "name": "taxId", + "optional": false, + "type": "string" + } + ] + }, + "checkApiHealth": "checkApiHealth" + } + }, + "webhooks": { + "className": "Webhooks", + "directory": "tools", + "methods": { + "create": "createWebhook", + "list": { + "operation": "listWebhooks", + "optional": { + "params": false + }, + "nullable": { + "params": false + } + }, + "retrieve": "getWebhook", + "update": "editWebhook", + "del": "deleteWebhook", + "validateSignature": { + "extension": "validateSignature" + } + } + } +} diff --git a/scripts/sync-openapi.mjs b/scripts/sync-openapi.mjs new file mode 100644 index 0000000..42721c8 --- /dev/null +++ b/scripts/sync-openapi.mjs @@ -0,0 +1,24 @@ +import { readFile, writeFile } from 'node:fs/promises' +import { readSpecification, resolveRevision } from './sdk/openapi-source.mjs' + +const root = new URL('../', import.meta.url) +const previous = JSON.parse( + await readFile(new URL('openapi/source.json', root), 'utf8'), +) +const source = { + repository: previous.repository, + revision: await resolveRevision( + previous.repository, + process.argv[2] || 'main', + ), + path: previous.path, +} +// Resolve first, then read from that exact commit even if the branch moves. +await readSpecification(source) +await writeFile( + new URL('openapi/source.json', root), + JSON.stringify(source, null, 2) + '\n', +) +console.log( + `Pinned the public specification to ${source.revision}. Run pnpm generate:sdk.`, +) diff --git a/src/enums.ts b/src/enums.ts index dc5e222..9b08e29 100644 --- a/src/enums.ts +++ b/src/enums.ts @@ -46,7 +46,7 @@ export const PaymentFormList = [ { value: '30', label: 'Aplicación de anticipos' }, { value: '31', label: 'Intermediario de pagos' }, { value: '99', label: 'Por definir' }, -] as const; +] as const export enum CustomsRegimes { DEFINITIVE_IMPORT = 'IMD', @@ -77,7 +77,7 @@ export const CUSTOMS_REGIMES_DESCRIPTION = { 'Recinto fiscalizado estratégico', [CustomsRegimes.FISCAL_ENCLOSURE]: 'Recinto fiscalizado', [CustomsRegimes.CUSTOMS_TRANSIT]: 'Tránsito aduanero', -}; +} export enum CveTransporteEnum { AUTOTRANSPORT = '01', @@ -93,7 +93,7 @@ export const CVE_TRANSPORT_DESCRIPTION = { [CveTransporteEnum.AIRLINE_TRANSPORT]: 'Transporte Aéreo', [CveTransporteEnum.RAIL_TRANSPORT]: 'Transporte Ferroviario', [CveTransporteEnum.OTHER]: 'Otro', -}; +} export enum TipoEstacionEnum { NATIONAL_ORIGIN = '01', @@ -105,7 +105,7 @@ export const TIPO_ESTACION_DESCRIPTION = { [TipoEstacionEnum.NATIONAL_ORIGIN]: 'Origen Nacional', [TipoEstacionEnum.INTERMEDIATE]: 'Intermedia', [TipoEstacionEnum.FINAL_DESTINATION]: 'Destino Final Nacional', -}; +} export enum PermisoSctEnum { FEDERAL_TRANSPORT_OF_LOAD = 'TPAF01', @@ -187,7 +187,7 @@ export const PERMISO_SCT_DESCRIPTIONS = { [PermisoSctEnum.NATIONAL_INTERNATIONAL_AIR_TAXI_SERVICE]: 'Permiso para el servicio nacional e internacional no regular de taxi aéreo', [PermisoSctEnum.NOT_IN_CATALOG]: 'Permiso no contemplado en el catálogo.', -}; +} export enum SectorCofeprisEnum { MEDICINE = '01', @@ -206,7 +206,7 @@ export const SECTOR_COFEPRIS_DESCRIPTIONS = { [SectorCofeprisEnum.TOXIC_SUBSTANCES]: 'Sustancias tóxicas', [SectorCofeprisEnum.PESTICIDES_AND_FERTILIZERS]: 'Plaguicidas y fertilizantes', -}; +} export enum PharmaceuticalFormsEnum { TABLET = '01', @@ -252,7 +252,7 @@ export const PHARMACEUTICAL_FORM_DESCRIPTIONS = { [PharmaceuticalFormsEnum.PASTE]: 'Pasta', [PharmaceuticalFormsEnum.POWDER]: 'Polvo', [PharmaceuticalFormsEnum.SUPPOSITORY]: 'Supositorio', -}; +} export enum SpecialConditionsEnum { FROZEN = '01', @@ -266,7 +266,7 @@ export const SPECIAL_CONDITION_DESCRIPTIONS = { [SpecialConditionsEnum.REFRIGERATED]: 'Refrigerados', [SpecialConditionsEnum.CONTROLLED_TEMPERATURE]: 'Temperatura controlada', [SpecialConditionsEnum.ROOM_TEMPERATURE]: 'Temperatura ambiente', -}; +} export enum MaterialTypeEnum { RAW_MATERIAL = '01', @@ -284,7 +284,7 @@ export const MATERIAL_TYPE_DESCRIPTIONS = { [MaterialTypeEnum.MANUFACTURING_INDUSTRY_MATERIAL]: 'Materia para la industria manufacturera', [MaterialTypeEnum.OTHER]: 'Otra', -}; +} export enum TypeOfCustomsDocumentEnum { PEDIMENT = '01', @@ -345,7 +345,7 @@ export const TYPE_OF_CUSTOMS_DOCUMENT_DESCRIPTIONS = { [TypeOfCustomsDocumentEnum.CROSSING_NOTICE_MERCHANDISE]: 'Aviso de cruce de mercancias', [TypeOfCustomsDocumentEnum.OTHER]: 'Otro', -}; +} export enum TransportTypeEnum { UNIT_TRUCK = 'PT01', @@ -375,7 +375,7 @@ export const TRANSPORT_TYPE_DESCRIPTIONS = { [TransportTypeEnum.CAR_OR_WAGON]: 'Carro o vagón', [TransportTypeEnum.CONTAINER]: 'Contenedor', [TransportTypeEnum.LOCOMOTIVE]: 'Locomotora', -}; +} export enum TransportFigureEnum { OPERATOR = '01', @@ -391,7 +391,7 @@ export const TRANSPORT_FIGURE_DESCRIPTIONS = { [TransportFigureEnum.LESSOR]: 'Arrendador', [TransportFigureEnum.NOTIFIED]: 'Notificado', [TransportFigureEnum.COORDINATED_MEMBER]: 'Integrante de Coordinados', -}; +} export enum RegistroIstmoEnum { COATZACOALCOS_I = '01', @@ -409,7 +409,7 @@ export const REGISTRO_ISTMO_DESCRIPTIONS = { [RegistroIstmoEnum.SAN_JUAN_EVANGELISTA]: 'San Juan Evangelista', [RegistroIstmoEnum.SALINA_CRUZ]: 'Salina Cruz', [RegistroIstmoEnum.SAN_BLAS_ATEMPA]: 'San Blas Atempa', -}; +} export enum LoadingKey { GENERAL_LOOSE_CARGO = 'CGS', @@ -427,7 +427,7 @@ export const LOADING_KEY_DESCRIPTIONS = { [LoadingKey.AGRICULTURAL_BULK]: 'Granel Agrícola', [LoadingKey.OTHER_FLUIDS]: 'Otros Fluidos', [LoadingKey.OIL_AND_DERIVATIVES]: 'Petróleo y Derivados', -}; +} export enum ConfigMaritimaEnum { SUPPLIER = 'B01', @@ -464,7 +464,7 @@ export const CONFIG_MARITIMA_DESCRIPTIONS = { [ConfigMaritimaEnum.TUG]: 'Remolcador', [ConfigMaritimaEnum.EXTRAORDINARY_SPECIALIZATION]: 'Extraordinaria especialización', -}; +} export enum RailTrafficTypeEnum { LOCAL_TRAFFIC = 'TT01', @@ -481,7 +481,7 @@ export const RAIL_TRAFFIC_TYPE_DESCRIPTIONS = { 'Tráfico interlineal recibido', [RailTrafficTypeEnum.INTERLINE_TRANSIT_TRAFFIC]: 'Tráfico interlineal en tránsito', -}; +} export enum ContainerTypeEnum { CONTAINER_20FT = 'TC01', @@ -497,7 +497,7 @@ export const CONTAINER_TYPE_DESCRIPTIONS = { [ContainerTypeEnum.CONTAINER_45FT]: 'Contenedor de 13.7 Mts de longitud', [ContainerTypeEnum.CONTAINER_48FT]: 'Contenedor de 14.6 Mts de longitud', [ContainerTypeEnum.CONTAINER_53FT]: 'Contenedor de 16.1 Mts de longitud', -}; +} export enum MaritimeContainerTypeEnum { REFRIGERATED_20FT = 'CM001', @@ -529,7 +529,7 @@ export const MARITIME_CONTAINER_TYPE_DESCRIPTIONS = { [MaritimeContainerTypeEnum.TANKER_SHIP]: 'Buque tanque', [MaritimeContainerTypeEnum.FERRY]: 'Ferri', [MaritimeContainerTypeEnum.TOURIST_FERRY]: 'Ferri – Turístico y vacíos', -}; +} export enum RailCarTypeEnum { BOXCAR = 'TC01', @@ -557,7 +557,7 @@ export const RAIL_CAR_TYPE_DESCRIPTIONS = { [RailCarTypeEnum.SPECIAL_CAR]: 'Carro Especial', [RailCarTypeEnum.PASSENGER]: 'Pasajeros', [RailCarTypeEnum.TRACK_MAINTENANCE]: 'Mantenimiento de Vía', -}; +} export enum RailServiceTypeEnum { RAILWAY_CARS = 'TS01', @@ -587,7 +587,7 @@ export const MOTIVO_TRASLADO_DESCRIPTION = { [MotivoTrasladoEnum.THIRD_PARTY_OWNED_GOODS_SHIPMENT]: 'Envío de mercancías propiedad de terceros', [MotivoTrasladoEnum.OTHER]: 'Otros', -}; +} export enum TaxType { IVA = 'IVA', @@ -731,6 +731,9 @@ export enum InvoiceComplementType { CUSTOM = 'custom', PAGO = 'pago', NOMINA = 'nomina', + CARTA_PORTE = 'carta_porte', + COMERCIO_EXTERIOR = 'comercio_exterior', + LEYENDAS_FISCALES = 'leyendas_fiscales', } export enum CancellationMotive { diff --git a/src/generated/contracts.ts b/src/generated/contracts.ts new file mode 100644 index 0000000..ceee6ad --- /dev/null +++ b/src/generated/contracts.ts @@ -0,0 +1,22 @@ +// Generated by pnpm generate:sdk. Do not edit directly. + +import type { operations as Input } from './input' +import type { operations as Output } from './output' +export type OperationId = keyof Input +type Content = T extends { content: infer C } ? C[keyof C] : never +export type OperationBody = Content< + NonNullable +> +export type OperationQuery = NonNullable< + Input[K]['parameters']['query'] +> +export type OperationPath = NonNullable< + Input[K]['parameters']['path'] +> +export type OperationResponse = { + [S in keyof Output[K]['responses']]: S extends number + ? `${S}` extends `2${string}` + ? Content + : never + : never +}[keyof Output[K]['responses']] diff --git a/src/generated/dates.ts b/src/generated/dates.ts new file mode 100644 index 0000000..30f51d5 --- /dev/null +++ b/src/generated/dates.ts @@ -0,0 +1,718 @@ +// Generated by pnpm generate:sdk. Do not edit directly. +import type { DatePlan } from '../runtime/dates' +export const datePlans: DatePlan[] = [ + { kind: 'none' }, + { kind: 'date' }, + { kind: 'date-time' }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 6 }, + }, + { kind: 'array', items: 5 }, + { kind: 'object', properties: { created_at: 1 } }, + { kind: 'object', properties: { object: 7 } }, + { + kind: 'object', + properties: { created_at: 1, canceled_at: 1, date: 1, complements: 8 }, + }, + { kind: 'array', items: 9 }, + { + kind: 'union', + variants: [ + { plan: 10, match: { type: ['pago'] } }, + { plan: 13, match: { type: ['nomina'] } }, + { plan: 0, match: { type: ['carta_porte'] } }, + { plan: 0, match: { type: ['comercio_exterior'] } }, + { plan: 0, match: { type: ['leyendas_fiscales'] } }, + { plan: 0, match: { type: ['custom'] } }, + ], + }, + { kind: 'object', properties: { data: 11 } }, + { kind: 'array', items: 12 }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'object', properties: { data: 14 } }, + { + kind: 'object', + properties: { + fecha_pago: 15, + fecha_inicial_pago: 15, + fecha_final_pago: 15, + receptor: 16, + }, + }, + { kind: 'date-time' }, + { kind: 'object', properties: { fecha_inicio_rel_laboral: 15 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 18 }, + }, + { kind: 'object', properties: { object: 7 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 20 }, + }, + { kind: 'object', properties: { object: 7 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 22 }, + }, + { kind: 'object', properties: { object: 7 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 24 }, + }, + { kind: 'object', properties: { object: 25 } }, + { kind: 'object', properties: { created_at: 1, date: 1, expires_at: 1 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 27 }, + }, + { kind: 'object', properties: { object: 25 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4, data: 29 }, + }, + { kind: 'object', properties: { object: 30 } }, + { + kind: 'object', + properties: { created_at: 1, edit_link_expires_at: 1, sat_validated_at: 1 }, + }, + { + kind: 'union', + variants: [ + { plan: 3, match: { type: ['invoice.global_invoice_created'] } }, + { plan: 17, match: { type: ['invoice.status_updated'] } }, + { plan: 19, match: { type: ['invoice.created_from_dashboard'] } }, + { plan: 21, match: { type: ['invoice.cancellation_status_updated'] } }, + { plan: 23, match: { type: ['receipt.self_invoice_complete'] } }, + { plan: 26, match: { type: ['receipt.status_updated'] } }, + { plan: 28, match: { type: ['customer.edit_link_completed'] } }, + ], + }, + { kind: 'object', properties: { expires_at: 1 } }, + { + kind: 'object', + properties: { created_at: 1, related_resource_messages: 4 }, + }, + { kind: 'object', properties: { gt: 1, gte: 1, lt: 1, lte: 1 } }, + { kind: 'object', properties: { created_at: 1 } }, + { + kind: 'object', + properties: { + fecha_pago: 15, + fecha_inicial_pago: 37, + fecha_final_pago: 37, + receptor: 38, + }, + }, + { + kind: 'union', + variants: [ + { plan: 0, match: {} }, + { plan: 1, match: {} }, + { plan: 0, match: {} }, + { plan: 0, match: {} }, + ], + }, + { kind: 'object', properties: { fecha_inicio_rel_laboral: 15 } }, + { + kind: 'object', + properties: { + fecha_pago: 15, + fecha_inicial_pago: 15, + fecha_final_pago: 15, + }, + }, + { kind: 'object', properties: { receptor: 38 } }, + { kind: 'object', properties: { receptor: 16 } }, + { kind: 'object', properties: { fecha_inicio_rel_laboral: 15 } }, + { + kind: 'union', + variants: [ + { plan: 44, match: { type: ['pago'] } }, + { plan: 0, match: { type: ['custom'] } }, + ], + }, + { kind: 'object', properties: { data: 11 } }, + { + kind: 'union', + variants: [ + { plan: 0, match: { type: ['custom'] } }, + { plan: 46, match: { type: ['pago'] } }, + ], + }, + { kind: 'object', properties: { data: 47 } }, + { + kind: 'union', + variants: [ + { plan: 0, match: {} }, + { plan: 48, match: { tipoCadPago: ['01'] } }, + { plan: 49, match: {} }, + ], + }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'array', items: 48 }, + { kind: 'object', properties: { data: 47 } }, + { + kind: 'union', + variants: [ + { plan: 0, match: { type: ['custom'] } }, + { plan: 50, match: { type: ['pago'] } }, + { plan: 52, match: { type: ['nomina'] } }, + { plan: 0, match: { type: ['carta_porte'] } }, + { plan: 0, match: { type: ['comercio_exterior'] } }, + { plan: 0, match: { type: ['leyendas_fiscales'] } }, + ], + }, + { kind: 'object', properties: { data: 36 } }, + { + kind: 'union', + variants: [ + { plan: 48, match: { tipoCadPago: ['01'] } }, + { plan: 49, match: {} }, + ], + }, + { + kind: 'union', + variants: [ + { plan: 55, match: { type: ['nomina'] } }, + { plan: 0, match: { type: ['custom'] } }, + ], + }, + { kind: 'object', properties: { data: 14 } }, + { + kind: 'union', + variants: [ + { plan: 0, match: { type: ['custom'] } }, + { plan: 57, match: { type: ['nomina'] } }, + ], + }, + { kind: 'object', properties: { data: 36 } }, + { kind: 'object', properties: { created_at: 1 } }, + { kind: 'object', properties: { data: 60 } }, + { kind: 'array', items: 58 }, + { kind: 'object', properties: { data: 62 } }, + { kind: 'array', items: 30 }, + { + kind: 'object', + properties: { edit_link_expires_at: 1, sat_validated_at: 1 }, + }, + { kind: 'object', properties: { created_at: 1 } }, + { kind: 'object', properties: { data: 66 } }, + { kind: 'array', items: 64 }, + { + kind: 'object', + properties: { + created_at: 1, + start_date: 1, + end_date: 1, + scheduled_at: 1, + processing_started_at: 1, + }, + }, + { kind: 'object', properties: { data: 69 } }, + { kind: 'array', items: 67 }, + { kind: 'object', properties: { created_at: 1, date: 1, complements: 8 } }, + { kind: 'object', properties: { data: 72 } }, + { kind: 'array', items: 7 }, + { kind: 'object', properties: { canceled_at: 1, date: 1, complements: 8 } }, + { kind: 'object', properties: { date: 1, complements: 8 } }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'object', properties: { date: 1 } }, + { + kind: 'union', + variants: [ + { plan: 79, match: { type: ['I'], status: ['pending'] } }, + { plan: 81, match: { type: ['I'], status: ['draft'] } }, + { + plan: 82, + match: { type: ['E'], payment_method: ['PUE'], status: ['pending'] }, + }, + { + plan: 83, + match: { type: ['E'], payment_method: ['PUE'], status: ['draft'] }, + }, + { plan: 84, match: { type: ['P'], status: ['pending'] } }, + { plan: 85, match: { type: ['P'], status: ['draft'] } }, + { plan: 86, match: { type: ['N'], status: ['pending'] } }, + { plan: 87, match: { type: ['N'], status: ['draft'] } }, + { plan: 88, match: { type: ['T'], status: ['pending'] } }, + { plan: 89, match: { type: ['T'], status: ['draft'] } }, + ], + }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'array', items: 51 }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { complements: 80, date: 1 } }, + { kind: 'object', properties: { date: 1, expires_at: 1 } }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'object', properties: { date: 1 } }, + { kind: 'object', properties: { data: 104 } }, + { kind: 'array', items: 25 }, + { + kind: 'union', + variants: [ + { plan: 106, match: {} }, + { plan: 107, match: {} }, + ], + }, + { kind: 'object', properties: { from: 15, to: 15, date: 15 } }, + { kind: 'object', properties: { from: 37, to: 37, date: 15 } }, + { kind: 'object', properties: { from: 15, to: 15, date: 15 } }, + { kind: 'object', properties: { created_at: 1, fecha_exp: 1 } }, + { kind: 'object', properties: { fecha_exp: 1 } }, + { kind: 'object', properties: { data: 112 } }, + { kind: 'array', items: 109 }, + { kind: 'object', properties: { fecha_exp: 1 } }, + { kind: 'object', properties: { fecha_exp: 1 } }, + { kind: 'object', properties: { data: 116 } }, + { kind: 'array', items: 117 }, + { + kind: 'object', + properties: { + created_at: 1, + certificate: 118, + fiel: 119, + pending_plan_update: 120, + pending_add_ons_update: 121, + }, + }, + { kind: 'object', properties: { updated_at: 1, expires_at: 1 } }, + { kind: 'object', properties: { updated_at: 1, expires_at: 1 } }, + { kind: 'object', properties: { scheduled_for: 1 } }, + { kind: 'object', properties: { scheduled_for: 1 } }, + { kind: 'object', properties: { updated_at: 1 } }, + { kind: 'object', properties: { created_at: 1, expires_at: 1 } }, + { kind: 'array', items: 123 }, + { kind: 'object', properties: { created_at: 1, updated_at: 1 } }, + { kind: 'array', items: 125 }, + { kind: 'object', properties: { created_at: 1, updated_at: 1 } }, + { kind: 'array', items: 127 }, + { + kind: 'union', + variants: [ + { plan: 30, match: {} }, + { plan: 30, match: {} }, + ], + }, + { + kind: 'union', + variants: [ + { plan: 7, match: {} }, + { plan: 70, match: {} }, + ], + }, + { + kind: 'union', + variants: [ + { plan: 130, match: {} }, + { plan: 0, match: {} }, + ], + }, + { + kind: 'union', + variants: [ + { plan: 7, match: {} }, + { plan: 0, match: {} }, + ], + }, + { kind: 'array', items: 134 }, + { kind: 'object', properties: { created_at: 1 } }, + { kind: 'array', items: 136 }, + { kind: 'object', properties: { created_at: 1 } }, +] +export const componentDatePlans = { + DateOrDateTime: 2, + InvoiceGlobalInvoiceCreatedEvent: 3, + InvoiceStatusUpdatedEvent: 17, + InvoiceCreatedFromDashboardEvent: 19, + InvoiceCancellationStatusUpdatedEvent: 21, + ReceiptSelfInvoiceCompleteEvent: 23, + ReceiptStatusUpdatedEvent: 26, + CustomerEditLinkCompletedEvent: 28, + ApiEvent: 31, + SignedDownloadUrl: 32, + SearchKeyDescriptionResult: 0, + RelatedResourceMessage: 5, + EventBase: 33, + DateRange: 34, + GenericError: 0, + ErrorDetail: 0, + IssuingType: 0, + CancellationStatus: 0, + SearchResult: 0, + ResourceAutoGeneratedProps: 35, + TaxIdValidationResult: 0, + ProductCatalogResult: 0, + UnitCatalogResult: 0, + ProductCatalogSearchResult: 0, + UnitCatalogSearchResult: 0, + LocalTax: 0, + BaseTax: 0, + IepsMode: 0, + IepsTax: 0, + Stamp: 0, + LineItem: 0, + ThirdParty: 0, + LineItemInput: 0, + LineItemEgresoInput: 0, + LineItemTrasladoInput: 0, + HidroYPetroComplementInput: 0, + IeduComplementInput: 0, + CustomComplementData: 0, + CustomComplementProperties: 0, + CustomComplementInput: 0, + NominaComplementDataInput: 36, + NominaComplementDataProperties: 14, + NominaComplementDataDirectProperties: 39, + NominaComplementDataNestedInput: 40, + NominaComplementDataNestedProperties: 41, + NominaIncapacidadInput: 0, + NominaIncapacidadProperties: 0, + NominaOtroPagoInput: 0, + NominaOtroPagoDirectProperties: 0, + NominaCompensacionInput: 0, + NominaCompensacionProperties: 0, + NominaDeduccionInput: 0, + NominaDeduccionProperties: 0, + NominaPercepcionesInput: 0, + NominaPercepcionesProperties: 0, + NominaSeparacionInput: 0, + NominaSeparacionProperties: 0, + NominaJubilacionInput: 0, + NominaJubilacionProperties: 0, + NominaPercepcionProperties: 0, + NominaPercepcionInput: 0, + NominaPercepcionDirectProperties: 0, + NominaPercepcionNestedInput: 0, + NominaPercepcionNestedProperties: 0, + NominaHorasExtraInput: 0, + NominaHorasExtraProperties: 0, + NominaAccionesInput: 0, + NominaAccionesProperties: 0, + NominaReceptorProperties: 16, + NominaReceptorInput: 38, + NominaReceptorDirectProperties: 42, + NominaReceptorNestedProperties: 0, + NominaReceptorNestedInput: 0, + NominaSubContratacionRequiredProperties: 0, + NominaSubContratacionProperties: 0, + NominaEntidadSncfInput: 0, + NominaEmisorInput: 0, + NominaEmisorProperties: 0, + PagoOrCustomComplementProperties: 43, + PagoOrCustomComplementInput: 45, + PagoComplementProperties: 10, + PagoComplementInput: 50, + InvoiceComplementInput: 51, + InvoiceComplementProperties: 9, + PagoComplementDataProperties: 11, + PaymentProperties: 12, + PagoComplementDataInput: 53, + NominaOrCustomComplementProperties: 54, + NominaOrCustomComplementInput: 56, + NominaComplementProperties: 13, + NominaComplementInput: 52, + CartaPorteProperties: 0, + CartaPorteInput: 0, + ComercioExteriorProperties: 0, + ComercioExteriorInput: 0, + LeyendasFiscalesProperties: 0, + LeyendasFiscalesInput: 0, + CartaPorteOrCustomComplementProperties: 0, + CartaPorteOrCustomComplementInput: 0, + LeyendasFiscalesData: 0, + CartaPorteDataProperties: 0, + CartaPorteDataInput: 0, + ComercioExteriorDataProperties: 0, + ComercioExteriorDataInput: 0, + ComercioExteriorDomicilio: 0, + ComercioExteriorEmisor: 0, + ComercioExteriorPropietario: 0, + ComercioExteriorReceptor: 0, + ComercioExteriorDestinatario: 0, + ComercioExteriorDescripcionesEspecificas: 0, + ComercioExteriorMercancia: 0, + ComercioExteriorMercancias: 0, + CartaPorteCantidadTransporta: 0, + CartaPorteDetalleMercancia: 0, + CartaPorteDocumentacionAduanera: 0, + CartaPorteGuiaIdentificacion: 0, + CartaPorteMercancia: 0, + CartaPorteIdentificacionVehicular: 0, + CartaPorteSeguros: 0, + CartaPorteRemolque: 0, + CartaPorteAutotransporte: 0, + CartaPorteContenedorMaritimo: 0, + CartaPorteTransporteMaritimo: 0, + CartaPorteTransporteAereo: 0, + CartaPorteDerechosDePaso: 0, + CartaPorteContenedorFerroviario: 0, + CartaPorteCarroFerroviario: 0, + CartaPorteTransporteFerroviario: 0, + CartaPorteDomicilio: 0, + CartaPorteMercancias: 0, + NamespaceRequiredProperties: 0, + NamespaceProperties: 0, + CommonAddressProperties: 0, + Webhook: 58, + WebhookSearchResult: 59, + WebhookProperties: 0, + WebhookCreateInput: 0, + WebhookCreateEdit: 0, + Customer: 30, + CustomerSearchResult: 61, + CustomerNonEditableProperties: 63, + CustomerProperties: 0, + CustomerCommonProperties: 0, + CancellationQueryInput: 0, + CustomerCreateWithEditLinkInput: 0, + CustomerCreateCommonInput: 0, + CustomerNationalAddressInput: 0, + CustomerForeignAddressInput: 0, + CustomerNationalCreateInput: 0, + CustomerForeignCreateInput: 0, + CustomerGenericCreateInput: 0, + CustomerCreateInput: 0, + LineItemProductInput: 0, + LineItemProductEgresoInput: 0, + LineItemTrasladoProductInput: 0, + LineItemProduct: 0, + Parts: 0, + PartInput: 0, + Product: 64, + ProductSearchResult: 65, + ProductProperties: 0, + ProductEditableProperties: 0, + ProductEgresoProperties: 0, + PaymentInput: 48, + CustomerInfo: 0, + CustomerComercioExterior: 0, + RelatedDocumentInput: 0, + RelatedDocument: 0, + InvoiceZipRequestStatus: 0, + InvoiceZipRequestInvoiceType: 0, + InvoiceZipRequestCreateInput: 0, + InvoiceZipRequest: 67, + InvoiceZipRequestSearchResult: 68, + Invoice: 7, + InvoiceDraft: 70, + InvoiceSearchResult: 71, + InvoiceRequiredProperties: 0, + InvoiceProperties: 73, + InvoiceDraftProperties: 74, + InvoiceableCommonInput: 0, + InvoiceableCommonEditInput: 0, + InvoiceCustomerInput: 0, + InvoiceCommonInputProperties: 75, + InvoiceCommonEditInputProperties: 76, + InvoiceDraftInputProperties: 77, + InvoiceCreateInput: 78, + InvoiceIngresoInput: 90, + InvoiceEgresoInput: 91, + InvoicePagoInput: 92, + InvoiceNominaInput: 93, + InvoiceTrasladoInput: 94, + InvoiceIngresoEditInput: 95, + InvoiceEgresoEditInput: 96, + InvoicePagoEditInput: 97, + InvoiceNominaEditInput: 98, + InvoiceTrasladoEditInput: 99, + Receipt: 25, + ReceiptProperties: 100, + ReceiptInput: 101, + ReceiptEditableProperties: 102, + ReceiptAssignCustomerInput: 0, + ReceiptSearchResult: 103, + InvoiceReceiptInput: 0, + GlobalInvoiceInput: 105, + GlobalInvoiceInputProperties: 108, + ToInvoiceInput: 0, + ToInvoicePreviewInput: 0, + ToInvoiceSummary: 0, + ReceiptInvoiceSummaryTax: 0, + Retention: 109, + RetentionReadOnlyProperties: 0, + RetentionProperties: 110, + RetentionSearchResult: 111, + RetentionInput: 113, + RetentionUpdateInput: 114, + OrganizationAddress: 0, + OrganizationSearchResult: 115, + Organization: 117, + OrganizationDeleteCerts: 122, + OrganizationCreateInput: 0, + OrganizationLegalInput: 0, + OrganizationCertsInput: 0, + OrganizationFielInput: 0, + OrganizationLogoInput: 0, + OrganizationCustomizationInput: 0, + OrganizationReceiptsInput: 0, + OrganizationSelfInvoiceInput: 0, + DomainField: 0, + OrganizationDomainInput: 0, + OrganizationSeriesCreateInput: 0, + OrganizationSeriesUpdateInput: 0, + OrganizationSeriesDefaultInput: 0, + OrganizationSeriesGroup: 0, + OkResponse: 0, + OrganizationInvite: 123, + OrganizationInviteList: 124, + OrganizationPermissionRole: 125, + OrganizationPermissionRoleList: 126, + OrganizationPermissionRoleTemplate: 0, + OrganizationPermissionRoleTemplateList: 0, + OrganizationPermissionOperationList: 0, + OrganizationUserAccess: 127, + OrganizationUserAccessList: 128, + OrganizationInviteCreateInput: 0, + OrganizationInviteRespondInput: 0, + OrganizationPermissionRoleCreateInput: 0, + OrganizationPermissionRoleUpdateInput: 0, + OrganizationUserAccessRoleUpdateInput: 0, +} as const +export const operationDatePlans = { + searchCartaPorteAirTransportCodes: 0, + searchComercioExteriorTariffFractions: 0, + searchCartaPorteTransportConfigs: 0, + searchCartaPorteRightsOfPassage: 0, + searchCartaPorteCustomsDocuments: 0, + searchCartaPortePackagingTypes: 0, + searchCartaPorteTrailerTypes: 0, + searchCartaPorteHazardousMaterials: 0, + searchCartaPorteNavalAuthorizations: 0, + searchCartaPortePortStations: 0, + searchCartaPorteMarineContainers: 0, + listCustomers: 61, + createCustomer: 129, + getCustomer: 30, + editCustomer: 30, + deleteCustomer: 30, + sendEditLinkByEmail: 0, + validateCustomerTaxInfo: 0, + listProducts: 65, + createProduct: 64, + getProduct: 64, + editProduct: 64, + deleteProduct: 64, + listInvoices: 71, + createInvoice: 131, + getInvoice: 7, + updateDraftInvoice: 70, + cancelInvoice: 7, + copyToDraftInvoice: 70, + stampDraftInvoice: 7, + updateInvoiceStatus: 7, + getInvoicePaymentSummary: 0, + previewInvoicePdf: 0, + previewInvoicePdfUrl: 32, + downloadInvoice: 0, + getInvoiceDownloadUrl: 32, + downloadCancellationReceiptXml: 0, + getCancellationReceiptDownloadUrl: 32, + sendInvoiceByEmail: 0, + listInvoiceZipRequests: 68, + createInvoiceZipRequest: 67, + retrieveInvoiceZipRequest: 67, + downloadInvoiceZipRequest: 0, + getInvoiceZipRequestDownloadUrl: 32, + listReceipts: 103, + createReceipt: 25, + getReceipt: 25, + assignReceiptCustomer: 25, + cancelReceipt: 25, + invoiceReceipt: 7, + createToInvoiceFromReceipts: 132, + previewToInvoiceFromReceipts: 0, + previewToInvoiceFromReceiptsUrl: 32, + createGlobalInvoice: 7, + downloadReceiptPdf: 0, + getReceiptDownloadUrl: 32, + sendReceiptByEmail: 0, + listRetentions: 111, + createRetention: 109, + getRetention: 109, + updateDraftRetention: 109, + cancelRetention: 109, + copyToDraftRetention: 109, + stampDraftRetention: 109, + downloadRetention: 0, + getRetentionDownloadUrl: 32, + sendRetentionByEmail: 0, + listOrganizations: 115, + createOrganization: 117, + meOrganization: 117, + getOrganization: 117, + deleteOrganization: 117, + editOrganizationLegal: 117, + uploadOrganizationCertificate: 117, + deleteOrganizationCertificate: 122, + uploadOrganizationFiel: 117, + uploadOrganizationLogo: 117, + editOrganizationCustomization: 117, + editOrganizationReceiptsSettings: 117, + editOrganizationSelfInvoiceSettings: 117, + checkDomainAvailability: 0, + editOrganizationDomain: 117, + getTestApiKey: 0, + renewTestApiKey: 0, + listLiveApiKeys: 133, + renewLiveApiKey: 0, + deleteLiveApiKey: 135, + getSeriesGroup: 0, + createSeriesGroup: 0, + updateDefaultSeries: 0, + updateSeriesGroup: 0, + deleteSeriesGroup: 0, + getOrganizationTeam: 128, + listOrganizationTeamInvites: 124, + createOrganizationTeamInvite: 123, + getOrganizationTeamUser: 127, + removeOrganizationUserAccess: 0, + deleteOrganizationTeamInvite: 0, + listPendingOrganizationInvites: 124, + respondOrganizationInvite: 0, + listOrganizationPermissionRoles: 126, + createOrganizationPermissionRole: 125, + listOrganizationPermissionRoleTemplates: 0, + listOrganizationPermissionOperations: 0, + getOrganizationPermissionRole: 125, + updateOrganizationPermissionRole: 125, + deleteOrganizationPermissionRole: 0, + updateOrganizationTeamUserRole: 127, + listWebhooks: 59, + createWebhook: 58, + getWebhook: 58, + editWebhook: 58, + deleteWebhook: 58, + validateWebhookSignature: 0, + checkApiHealth: 0, + validateTaxId: 0, + searchProducts: 0, + searchUnits: 0, + onInvoiceGlobalInvoiceCreated: 0, + onInvoiceStatusUpdated: 0, + onInvoiceCreatedFromDashboard: 0, + onInvoiceCancellationStatusUpdated: 0, + onReceiptSelfInvoiceComplete: 0, + onReceiptStatusUpdated: 0, + onCustomerEditLinkCompleted: 0, +} as const diff --git a/src/generated/input.ts b/src/generated/input.ts new file mode 100644 index 0000000..2b7947d --- /dev/null +++ b/src/generated/input.ts @@ -0,0 +1,11087 @@ +// Generated by pnpm generate:sdk. Do not edit directly. +import type { BinaryInput } from '../types/runtime' +export interface paths { + '/catalogs/cartaporte/3.1/air-transport-codes': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar códigos de transporte aéreo + * Devuelve entradas del catálogo de aerolíneas que coinciden con la consulta. Usado para el complemento Carta Porte. + */ + get: operations['searchCartaPorteAirTransportCodes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/comercioexterior/2.0/tariff-fractions': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar fracciones arancelarias + * Devuelve fracciones arancelarias que coinciden con la consulta. + */ + get: operations['searchComercioExteriorTariffFractions'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/transport-configs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar configuraciones de autotransporte + * Devuelve configuraciones de transporte (p. ej., camión/semirremolque). + */ + get: operations['searchCartaPorteTransportConfigs'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/rights-of-passage': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar derechos de paso + * Devuelve derechos de paso ferroviarios que coinciden con la consulta. + */ + get: operations['searchCartaPorteRightsOfPassage'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/customs-documents': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar documentos aduaneros + * Devuelve tipos de documentos aduaneros. + */ + get: operations['searchCartaPorteCustomsDocuments'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/packaging-types': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar tipos de empaque + * Devuelve tipos de empaque para mercancías. + */ + get: operations['searchCartaPortePackagingTypes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/trailer-types': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar tipos de remolque + * Devuelve tipos de remolque/semirremolque. + */ + get: operations['searchCartaPorteTrailerTypes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/hazardous-materials': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar materiales peligrosos + * Devuelve entradas del catálogo de materiales peligrosos. + */ + get: operations['searchCartaPorteHazardousMaterials'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/naval-authorizations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar autorizaciones navales + * Devuelve códigos de autorización naval (solo `key`). + */ + get: operations['searchCartaPorteNavalAuthorizations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/port-stations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar estaciones/puertos + * Devuelve entradas de estaciones aéreas/marítimas/terrestres. + */ + get: operations['searchCartaPortePortStations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/marine-containers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar contenedores marítimos + * Devuelve tipos de contenedores marítimos. + */ + get: operations['searchCartaPorteMarineContainers'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar clientes + * Regresa una lista paginada de todos los clientes de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listCustomers'] + put?: never + /** + * Crear cliente + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + */ + post: operations['createCustomer'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener cliente por ID + * Regresa el objeto 'Customer' relacionado al `id` especificado. + */ + get: operations['getCustomer'] + /** + * Editar cliente + * Actualiza la información de un cliente existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + */ + put: operations['editCustomer'] + post?: never + /** + * Eliminar cliente + * Elimina el cliente de tu organización. Las facturas asociadas al cliente **no** se eliminarán. + */ + delete: operations['deleteCustomer'] + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}/email-edit-link': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar enlace de edición por correo electrónico + * Envía un enlace para que el cliente pueda editar su información fiscal. + * + * Este enlace estará disponible en el campo `edit_link`, será válido por 3 días y sólo se podrá usar una vez. + */ + post: operations['sendEditLinkByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}/tax-info-validation': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Validar información fiscal + * Valida que la información fiscal del cliente coincida con los registros del SAT. + * + * Su función principal es validar que los datos del cliente registrado siguen cumpliendo la validación del SAT. + * + * :::tip + * Las operaciones de crear cliente, editar cliente y crear factura ya realizan una + * validación de la información del cliente, por lo que **no** es necesario llamar a este endpoint + * antes de realizar dichas operaciones. + * ::: + */ + get: operations['validateCustomerTaxInfo'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/products': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar productos + * Regresa una lista paginada de todos los productos de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listProducts'] + put?: never + /** + * Crear producto + * Registra un nuevo producto o servicio en tu catálogo de Facturapi. + * + * Puedes usar el ID del producto para crear facturas sin tener que enviar todos los datos del producto cada vez. + * + * Ten en cuenta que los productos que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + */ + post: operations['createProduct'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/products/{product_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener producto por ID + * Regresa el objeto `Product` relacionado al `id` especificado. + */ + get: operations['getProduct'] + /** + * Editar producto + * Actualiza la información de un producto existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + */ + put: operations['editProduct'] + post?: never + /** + * Eliminar producto + * Elimina el producto de tu organización. Las facturas asociadas al producto **no** se eliminarán. + */ + delete: operations['deleteProduct'] + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar facturas + * Regresa una lista paginada de todas las facturas de una organización o realiza una búsqueda de acuerdo a parámetros. + * + * Por defecto, los resultados se ordenan por fecha de emisión, usando el campo `date` de forma descendente. + */ + get: operations['listInvoices'] + put?: never + /** + * Crear factura (CFDI 4.0) + * Crea una nueva Factura. Si la factura es creada en ambiente Live, ésta será **timbrada y enviada al SAT**. + * + * Revisa e infórmate sobre el [rescate de CFDI en intermitencias (Status 202)](/docs/guides/invoices/intermitencias). + */ + post: operations['createInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener factura por ID + * Regresa el objeto 'Invoice' relacionado al `id` especificado. + */ + get: operations['getInvoice'] + /** + * Editar borrador de factura + * Actualiza la información de una factura con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * En el objeto `invoice` de respuesta, Facturapi asignará automáticamente + * el campo `is_ready_to_stamp` con el valor `true` si la factura pasa la + * validación mínima requerida para ser timbrada; de lo contrario, el campo + * `is_ready_to_stamp` será `false`. + */ + put: operations['updateDraftInvoice'] + post?: never + /** + * Cancelar factura + * Realiza una solicitud de cancelación de factura ante el SAT, soportando el esquema de cancelación 2022. + * + * Al usar este método pueden ocurrir 3 posibles resultados: + * + * - Que la llamada regrese un error con la explicación de por qué no se pudo cancelar. + * - Que la llamada sea satisfactoria y regrese un objeto `invoice` con la propiedad `status: "canceled"`. + * - Que la llamada sea satisfactoria, pero que la cancelación requiera de confirmación de parte de tu cliente, en cuyo caso se obtendrá como respuesta el objeto `invoice` con las propiedades `status: "valid"` y `cancellation_status: "pending"`. + * + * En el tercer escenario, el valor de `cancellation_status` será actualizado automáticamente por Facturapi cuando tu cliente acepte, rechace o deje expirar la solicitud, de tal manera que al consultar una factura (usando [Obtener Factura](#tag/invoice/operation/getInvoice)), la propiedad `cancellation_status` reflejará el estado más reciente de la solicitud. + * + * Consulta los valores posibles de `cancellation_status` más abajo. + * + * Después de la cancelación la factura ya no tendrá validez, el objeto cambiará su `status` a `"canceled"` y seguirá estando disponible para futuras consultas. + * + * Si el status de la factura es `draft`, este método la eliminará de la base de datos. + * + * Si el status de la factura es `canceled`, este método regresará un error. + */ + delete: operations['cancelInvoice'] + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/copy': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Copiar a borrador + * Crea una copia en borrador de la factura especificada. + */ + post: operations['copyToDraftInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/stamp': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Timbrar borrador de factura + * Timbra una factura con status `draft` y la envía al SAT para su validación. + * + * Al usar este método, el valor del campo `is_ready_to_stamp` (asignado por Facturapi) + * deberá ser `true`. De otra forma, la llamada regresará un error. + * + * Este método no permite editar la factura, sólo timbrarla. Si necesitas editar información + * en la factura antes de timbrarla, usa el método [Editar Borrador de Factura](#tag/invoice/operation/editDraftInvoice). + */ + post: operations['stampDraftInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/status': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Actualizar status de factura + * Consulta el status de una factura timbrada en el SAT y actualiza el objeto invoice + * con La información más reciente. + */ + put: operations['updateInvoiceStatus'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/payment-summary': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Resumen de pago + * Devuelve la información necesaria para agregar esta factura como documento relacionado en un + * Comprobante de Pago (complemento de pago): el número de parcialidad que corresponde según el + * historial de pagos, el saldo anterior (`last_balance`) y el desglose de impuestos de la factura + * prorrateado al monto que se pretende pagar. + * + * El valor de retorno está listo para usarse como elemento de `related_documents` al + * [crear una factura de tipo Pago](#tag/invoice/operation/createInvoice). + * + * El parámetro `amount` debe expresarse en la divisa de la factura y no puede exceder el saldo + * pendiente (`amount_due`). Cuando el pago se recibe en otra divisa, convierte el monto antes de + * llamar este método. + */ + get: operations['getInvoicePaymentSummary'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/preview/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Vista previa de factura en PDF + * Genera una vista previa en PDF de una factura sin timbrar ni guardar en la organización. + */ + post: operations['previewInvoicePdf'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/preview/pdf/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Obtener URL del preview PDF de factura + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura sin timbrar. + */ + post: operations['previewInvoicePdfUrl'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar factura + * Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + */ + get: operations['downloadInvoice'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la factura en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getInvoiceDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/cancellation_receipt/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar acuse de cancelación + * Descarga en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + */ + get: operations['downloadCancellationReceiptXml'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/cancellation_receipt/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace del acuse de cancelación + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getCancellationReceiptDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar factura por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + */ + post: operations['sendInvoiceByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar solicitudes de ZIP mensual + * Regresa una lista paginada de solicitudes de ZIP. `year` y `month` deben enviarse juntos. `invoice_types` filtra por un tipo o por un arreglo normalizado exacto. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['listInvoiceZipRequests'] + put?: never + /** + * Crear o recuperar solicitud de ZIP mensual + * Crea una solicitud para generar un archivo ZIP con las facturas de un mes, o recupera la solicitud existente con los mismos filtros. + * + * La operación es idempotente. Los tipos de factura se normalizan, por lo que `["I", "E"]` y `["E", "I"]` corresponden a la misma solicitud. Las llamadas concurrentes idénticas también regresan la misma solicitud. + * + * Si una solicitud anterior tiene status `failed`, volver a llamar este método reintentará su procesamiento. Antes del nuevo intento se limpian el error, la tarea anterior, el progreso procesado y la lista de documentos fallidos. Si no es posible programar la generación, la solicitud se guarda con status `failed` y la API regresa un error `5xx`. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. Las llaves de ambiente Test regresan HTTP 402. + */ + post: operations['createInvoiceZipRequest'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Recuperar solicitud de ZIP mensual + * Recupera una solicitud de ZIP. Consulta este método hasta que el status sea `finished` o `failed`. Cuando sea `finished`, descarga el archivo con el método de descarga. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['retrieveInvoiceZipRequest'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}/zip': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar ZIP mensual + * Descarga el ZIP de una solicitud terminada. El nombre del archivo usa el formato `YYYY-MM.zip`. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['downloadInvoiceZipRequest'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener URL de descarga del ZIP mensual + * Devuelve un objeto con los metadatos del archivo y una URL temporal para descargar el ZIP de una solicitud terminada sin que el archivo viaje a través de tu servidor. + * + * La URL permite acceder únicamente a ese archivo mientras sea válida: trátala como una credencial y no la almacenes. Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['getInvoiceZipRequestDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar recibos + * Regresa una lista paginada de todos los recibos de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listReceipts'] + put?: never + /** + * Crear recibo + * Crea un nuevo Recibo, el cual funge como nota de venta. + * + * Todos los recibos generan una URL de autofactura que cliente puede + * visitar para llenar sus datos fiscales en un micrositio con el branding + * de la organización. + */ + post: operations['createReceipt'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener recibo por ID + * Regresa el objeto 'Receipt' relacionado al `id` especificado. + */ + get: operations['getReceipt'] + /** + * Asignar o reasignar cliente a recibo + * Asigna o reasigna un cliente existente (por ID) a un recibo, o crea uno nuevo enviando el objeto del cliente. + */ + put: operations['assignReceiptCustomer'] + post?: never + /** + * Cancelar recibo + * Marca un recibo como cancelado, cambiando su propiedad `status` a `"canceled"`. + * + * Una vez cancelado, el recibo no podrá ser facturado. + */ + delete: operations['cancelReceipt'] + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Facturar recibo + * Crea una factura a partir de un recibo. + * + * Sólo pueden facturarse recibos abiertos (`status = "open"`) + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado al recibo. Si omites `customer`, el + * recibo debe tener un cliente asignado previamente. + * + * Una vez facturado, el `status` del recibo cambiará a `"invoiced_to_customer"`. + */ + post: operations['invoiceReceipt'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Facturar múltiples recibos + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + */ + post: operations['createToInvoiceFromReceipts'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice/preview': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Vista previa PDF de factura múltiple + * Genera una vista previa en PDF para una factura construida a partir de múltiples recibos seleccionados por `key`. + * + * La vista previa valida las mismas reglas de cliente que la creación real: + * si omites `customer`, todos los recibos deben tener asignado el mismo cliente. + */ + post: operations['previewToInvoiceFromReceipts'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice/preview/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Obtener URL del preview de factura de recibos + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura construida con los recibos seleccionados. + */ + post: operations['previewToInvoiceFromReceiptsUrl'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/global-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Crear factura global + * Crea una factura global que incluirá todos los recibos con `status = “open”` de un cierto periodo. + * + * La factura global se emite al cliente genérico `PUBLICO EN GENERAL`. + * Los recibos incluidos quedan asociados a ese cliente y su `status` + * cambia a `"invoiced_globally"`. + * + * Una factura global puede incluir hasta 5,000 recibos abiertos. Si el periodo + * contiene más, puedes enviar `limit_to_max_receipts: true` y repetir la solicitud + * con el mismo periodo hasta recibir `null`. + */ + post: operations['createGlobalInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar PDF + * Descarga el recibo digital en formato PDF. + */ + get: operations['downloadReceiptPdf'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/download-url/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar el recibo digital en PDF, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getReceiptDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar recibo por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente. + * + * El correo enviado estará personalizado con el logotipo y los colores de la organización que lo creó, + * e incluirá un botón para facturar el recibo, así con el recibo en formato PDF adjunto al mensaje. + */ + post: operations['sendReceiptByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar retenciones + * Regresa una lista paginada de todas las retenciones de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listRetentions'] + put?: never + /** + * Crear retención + * Crea una nueva Retención. Si el comprobante es creado en ambiente Live, ésta será **timbrado y enviado al SAT**. + * + * Para crear una retención en borrador, envía `status: "draft"`. En ese caso, + * la retención se guardará sin timbrarse, no se enviará al PAC y podrá estar + * incompleta. Facturapi asignará `is_ready_to_stamp: true` únicamente cuando + * el borrador tenga todos los datos requeridos para timbrarse. + */ + post: operations['createRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener retención por ID + * Regresa el objeto 'Retention' relacionado al `id` especificado. + */ + get: operations['getRetention'] + /** + * Editar borrador de retención + * Actualiza la información de una retención con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * Facturapi recalculará automáticamente `is_ready_to_stamp` después de cada + * edición. Si la retención ya no está en status `draft`, la llamada regresará + * un error. + */ + put: operations['updateDraftRetention'] + post?: never + /** + * Cancelar retención + * Realiza una solicitud de cancelación de retención ante el SAT. + * + * A diferencia de las facturas comunes, la cancelación de la retención es inmediata y no requiere autorización de parte del receptor. + * + * Si el status de la retención es `draft`, este método la eliminará de la + * base de datos sin llamar al SAT/PAC y sin requerir parámetros de cancelación. + */ + delete: operations['cancelRetention'] + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/copy': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Copiar a borrador + * Crea una copia en borrador de la retención especificada. La copia no conserva + * campos propios del timbrado, cancelación, idempotencia o identidad externa. + */ + post: operations['copyToDraftRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/stamp': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Timbrar borrador de retención + * Timbra una retención con status `draft` y la envía al SAT para su validación. + * + * Facturapi validará el borrador como una retención completa antes de timbrarlo. + * Si el borrador está incompleto o no es válido, la llamada regresará un error. + */ + post: operations['stampDraftRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar retención + * Descarga una retención en PDF, XML o ambos en un archivo comprimido ZIP. + */ + get: operations['downloadRetention'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la retención en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getRetentionDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar retención por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + */ + post: operations['sendRetentionByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar organizaciones + * Regresa una lista paginada de todas las organizationes registradas bajo tu cuenta, o realiza una búsqueda de acuerdo a parámetros. + */ + get: operations['listOrganizations'] + put?: never + /** + * Crear organización + * Crea una nueva Organización que pertenecerá a tu cuenta de usuario. + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](#tag/organization/operation/uploadOrganizationCertificate) + * + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](#tag/organization/operation/uploadOrganizationCertificate), + * además de firmar la Carta Manifiesto que autoriza a nuestro PAC a timbrar facturas; + * puedes hacerlo en [tu dashboard](https://dashboard.facturapi.io/settings/manifiesto) + * o en [nuestro portal público](https://www.facturapi.io/manifiesto). También puedes incrustar + * en tu solución el módulo de firma de la carta (sin logos, listo para iframe): https://www.facturapi.io/embedded/manifiesto + * + * Recuerda que los folios de tu suscripción podrán ser consumidos por + * cualquiera de las organizaciones registradas bajo tu cuenta. + */ + post: operations['createOrganization'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/me': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Detalle de organización + * Retorna el detalle de la organización actualmente autenticada. + */ + get: operations['meOrganization'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener organización por ID + * Regresa el objeto 'Organization' relacionado al `id` especificado. + */ + get: operations['getOrganization'] + put?: never + post?: never + /** + * Eliminar organización + * Elimina la organización de tu cuenta de Facturapi. Una vez eliminada, + * ya no podrás acceder a sus recursos, tales como clientes, productos, + * facturas, recibos o retenciones. + */ + delete: operations['deleteOrganization'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/legal': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar datos fiscales + * Actualiza los datos fiscales de la organización. + * + * Si estás buscando cómo editar el RFC, recuerda que la propiedad + * `tax_id` se asigna automáticamente al subir los Certificados de Sello + * Digital. + */ + put: operations['editOrganizationLegal'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/certificate': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir certificados (CSD) + * Sube los archivos del Certificado de Sello Digital (CSD) proporcionado + * por el SAT. Esta llamada también debe usarse para reemplazar los + * certificados existentes en caso de solicitar nuevos. + * + * Al actualizar tus certificados se leerá el RFC y asignará + * automáticamente a `legal.tax_id`. + */ + put: operations['uploadOrganizationCertificate'] + post?: never + /** + * Eliminar certificados (CSD) + * Elimina los certificados (CSD) de tu organización. + * + * Esto no afecta a las facturas ya emitidas, pero no podrás emitir nuevas facturas hasta que subas nuevos certificados. + */ + delete: operations['deleteOrganizationCertificate'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/fiel': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir certificado FIEL + * Sube los archivos de la e.firma (FIEL) de la organización. + * + * La e.firma (FIEL) no es necesaria para crear CFDI. Para timbrar CFDI + * solo necesitas cargar el Certificado de Sello Digital (CSD). La FIEL es + * necesaria para utilizar la descarga masiva de CFDI. + */ + put: operations['uploadOrganizationFiel'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/logo': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir logotipo + * Sube el logotipo de la organización que será colocado en el PDF y en + * los correos que se envían al cliente con la factura adjunta. + * + * El archivo debe ser una imagen en formato JPG o PNG y tener un tamaño + * no mayor a 500 KB. Las dimensiones recomendadas son 800 × 500px. + * + * Si la organización ya tiene un logotipo, esta llamada reemplaza el + * logotipo anterior. + */ + put: operations['uploadOrganizationLogo'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/customization': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar personalización + * Actualiza la información relacionada con la identidad o branding de la organización. + */ + put: operations['editOrganizationCustomization'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/receipts': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar config. recibos + * Actualiza los campos enviados de la configuración de recibos de la organización. + * Para activar la generación automática de facturas globales, la organización + * debe tener contratado ese feature. + */ + put: operations['editOrganizationReceiptsSettings'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/self-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar config. autofactura + * Actualiza la configuración del portal de autofactura de la organización. + */ + put: operations['editOrganizationSelfInvoiceSettings'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/domain-check': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Revisar dominio disponible + * Revisa si un identificador está disponible para elegir como dominio para el portal de autofactura. + */ + get: operations['checkDomainAvailability'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/domain': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Elegir dominio de autofactura + * Elige el dominio que utilizará esta organización en su micrositio de + * autofactura. Una vez elegido el dominio, deberás ponerte en contacto + * con nosotros si necesitas cambiarlo. + * + * El dominio que elijas será el que aparecerá en el campo + * `self_invoice_url` al crear un nuevo recibo, de la siguiente manera: + * + * `https://factura.space/{DOMAIN}/{RECEIPT_KEY}` + */ + put: operations['editOrganizationDomain'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/test': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener Test Api Key + * Obtiene la llave secreta de ambiente Test de la organización. + */ + get: operations['getTestApiKey'] + /** + * Renovar Test API Key + * Renueva la llave secreta de ambiente Test de la organización e invalida inmediatamente la anterior. + */ + put: operations['renewTestApiKey'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/live': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar Live API Keys + * Listar llaves secretas de ambiente Live de la organización. + */ + get: operations['listLiveApiKeys'] + /** + * Crear Live API Key + * Genera una nueva llave secreta de ambiente Live de la organización. + * Esta operación no invalida las llaves generadas previamente. El endpoint usa `PUT` + * por compatibilidad histórica, pero su comportamiento es crear una nueva llave. + */ + put: operations['renewLiveApiKey'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/live/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Revocar Live API Key + * Revocar Live Api Key de tu organización. + */ + delete: operations['deleteLiveApiKey'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listado de series + * Listado de series creadas para la personalización de organización. La cual lleva control de foliaje para cada tipo de factura si está asignada en las personalización de organización. + */ + get: operations['getSeriesGroup'] + put?: never + /** + * Crear serie + * Crea una nueva serie de folios para la organización. + * Las series son útiles para llevar un control de los folios emitidos para cada tipo de factura. + */ + post: operations['createSeriesGroup'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group/default-series': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Establecer serie predeterminada + * Asigna una serie predeterminada para el tipo de comprobante indicado. + */ + put: operations['updateDefaultSeries'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group/{series_name}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar serie + * Edita el número de foliaje de la serie en ambientes Test y Live de la organización. + */ + put: operations['updateSeriesGroup'] + post?: never + /** + * Eliminar serie + * Elimina la serie previamente creada + */ + delete: operations['deleteSeriesGroup'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar usuarios con acceso a organización + * Regresa un arreglo con los usuarios que actualmente tienen acceso a la organización, incluyendo al propietario. Este endpoint no está paginado. + */ + get: operations['getOrganizationTeam'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/invites': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar invitaciones enviadas + * Regresa invitaciones enviadas desde la organización. + */ + get: operations['listOrganizationTeamInvites'] + put?: never + /** + * Invitar usuario a organización + * Crea o actualiza una invitación de usuario. Por defecto, el acceso es de administrador con permisos completos; para limitarlo, crea un rol y envía su ID en `role`. + * + * Cada organización puede invitar a un usuario sin costo adicional. A partir del segundo usuario invitado, cada usuario adicional tendrá un costo mensual. Este cargo se aplica automáticamente cuando el usuario acepta la invitación. + * Puedes consultar el precio vigente en nuestra [página de precios](https://www.facturapi.io/pricing). + */ + post: operations['createOrganizationTeamInvite'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/{access_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener acceso de usuario + * Regresa el detalle del acceso del usuario dentro de la organización usando su `access_id`, incluyendo accesos implícitos como el del propietario. + */ + get: operations['getOrganizationTeamUser'] + put?: never + post?: never + /** Eliminar usuario con acceso */ + delete: operations['removeOrganizationUserAccess'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/invites/{invite_key}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Cancelar invitación enviada + * Elimina una invitación pendiente de la organización. + */ + delete: operations['deleteOrganizationTeamInvite'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/invites/pending': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar invitaciones recibidas + * Regresa las invitaciones recibidas para el usuario autenticado. + */ + get: operations['listPendingOrganizationInvites'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/invites/{invite_key}/response': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Responder invitación + * Acepta o rechaza una invitación usando su `invite_key`. + */ + post: operations['respondOrganizationInvite'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar roles de organización */ + get: operations['listOrganizationPermissionRoles'] + put?: never + /** Crear rol de organización */ + post: operations['createOrganizationPermissionRole'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/templates': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar plantillas de roles */ + get: operations['listOrganizationPermissionRoleTemplates'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/operations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar operaciones de permisos */ + get: operations['listOrganizationPermissionOperations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/{role_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Obtener rol de organización */ + get: operations['getOrganizationPermissionRole'] + /** Actualizar rol de organización */ + put: operations['updateOrganizationPermissionRole'] + post?: never + /** Eliminar rol de organización */ + delete: operations['deleteOrganizationPermissionRole'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/{access_id}/role': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** Reasignar rol a usuario */ + put: operations['updateOrganizationTeamUserRole'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar webhooks + * Retorna una lista de webhooks creados previamente para la organización. + */ + get: operations['listWebhooks'] + put?: never + /** + * Crear Webhook + * Registra un nuevo webhook en tu organización de Facturapi. + * Utiliza esta llamada para recibir notificaciones de eventos asíncronos a la API. + * Los webhooks de ambiente test y ambiente live son independientes. + */ + post: operations['createWebhook'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks/{webhook_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener webhook por ID + * Regresa el objeto "Webhook" relacionado al `id` especificado. + */ + get: operations['getWebhook'] + /** + * Editar webhook + * Actualiza la información de un Webhook existente con los parámetros que envíes en la petición. + */ + put: operations['editWebhook'] + post?: never + /** + * Eliminar Webhook + * Elimina el webhook perteneciente a la organización. + */ + delete: operations['deleteWebhook'] + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks/validate-signature': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Validar evento de webhook + * Valida la firma de un evento recibido mediante un Webhook. + * Utiliza esta operación para verificar la autenticidad e integridad de + * un evento recibido, comparando la firma recibida con la generada por Facturapi. + */ + post: operations['validateWebhookSignature'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/check': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Health check (Pulso) + * Comprueba que la API está disponible. Este endpoint requiere una llave secreta de API. + */ + get: operations['checkApiHealth'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/tools/tax_id_validation': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Validar RFC + * Consulta el estado de un RFC en la lista de **EFOS** (Empresas que + * Facturan Operaciones Simuladas). Al aparecer en esta lista, el RFC es o + * fue sospechoso de incurrir en simulación de operaciones fiscales + * (empresas factureras). + * + * La respuesta (detallada más abajo) incluye los resultados de esta + * validación. Se incluye la propiedad + * booleana `is_valid`, que Facturapi resuelve interpretando la respuesta. + * Un valor de `true` para esta propiedad indica que el RFC no tiene asuntos + * por resolver y está libre de problemas; y lo contrario para `false`. + * + * Adicionalmente puedes consultar la propiedad data para ver los valores + * en bruto de la consulta al SAT. + */ + get: operations['validateTaxId'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/products': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Clave Producto/Servicio + * Busca en el catálogo Productos/Servicios del SAT, el cual contiene la clave a incluir en la factura. + */ + get: operations['searchProducts'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/units': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Unidades de medida + * Busca en el catálogo de Unidades de Medida del SAT. + */ + get: operations['searchUnits'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export interface webhooks { + 'invoice.global_invoice_created': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Factura global creada + * Notifica acerca de la creación de una factura global a partir de e-Receipts. + */ + post: operations['onInvoiceGlobalInvoiceCreated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de factura actualizado + * Notifica acerca del cambio del campo `status` de una factura. + * + * Se utiliza cuando la factura se crea de manera asíncrona o cuando una tarea de recuperación por intermitencia de timbrado cambia su estado. + */ + post: operations['onInvoiceStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.created_from_dashboard': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Creación de factura desde dashboard + * Notifica cuandos se crea una factura desde dashboard de Facturapi. + */ + post: operations['onInvoiceCreatedFromDashboard'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.cancellation_status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de cancelación actualizado + * Notifica acerca de cambios en el campo `cancellation_status` de una factura. + */ + post: operations['onInvoiceCancellationStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'receipt.self_invoice_complete': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Autofactura completada + * Notifica acerca de la creación de una autofactura a partir de un e-Receipt. + */ + post: operations['onReceiptSelfInvoiceComplete'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'receipt.status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de recibo actualizado + * Notifica acerca de cambios en el campo `status` de un recibo. + */ + post: operations['onReceiptStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'customer.edit_link_completed': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Edición de cliente completada */ + post: operations['onCustomerEditLinkCompleted'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export interface components { + schemas: { + /** Fecha en formato YYYY-MM-DD o fecha y hora en formato ISO8601. */ + DateOrDateTime: string | (Date | string) + InvoiceGlobalInvoiceCreatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.global_invoice_created' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.global_invoice_created' + } + InvoiceStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.status_updated' + } + InvoiceCreatedFromDashboardEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.created_from_dashboard' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.created_from_dashboard' + } + InvoiceCancellationStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.cancellation_status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.cancellation_status_updated' + } + ReceiptSelfInvoiceCompleteEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'receipt.self_invoice_complete' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'receipt' + object: components['schemas']['Receipt'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'receipt.self_invoice_complete' + } + ReceiptStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'receipt.status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'receipt' + object: components['schemas']['Receipt'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'receipt.status_updated' + } + CustomerEditLinkCompletedEvent: components['schemas']['EventBase'] & { + /** @enum {string} */ + type: 'customer.edit_link_completed' + data: { + /** @enum {string} */ + type: 'customer' + object: components['schemas']['Customer'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'customer.edit_link_completed' + } + ApiEvent: + | components['schemas']['InvoiceGlobalInvoiceCreatedEvent'] + | components['schemas']['InvoiceStatusUpdatedEvent'] + | components['schemas']['InvoiceCreatedFromDashboardEvent'] + | components['schemas']['InvoiceCancellationStatusUpdatedEvent'] + | components['schemas']['ReceiptSelfInvoiceCompleteEvent'] + | components['schemas']['ReceiptStatusUpdatedEvent'] + | components['schemas']['CustomerEditLinkCompletedEvent'] + /** Objeto con un enlace temporal de descarga y los metadatos del archivo. */ + SignedDownloadUrl: { + /** + * Format: uri + * Enlace de descarga. Da acceso al archivo mientras siga vigente. + */ + url: string + /** + * Format: date-time + * Momento en el que el enlace deja de funcionar. + */ + expires_at: Date | string + /** Tipo de contenido del archivo. */ + content_type: string + /** Nombre sugerido del archivo. */ + filename: string + } + SearchKeyDescriptionResult: components['schemas']['SearchResult'] & { + data?: { + /** Clave del catálogo */ + key?: string + /** Descripción de la entrada del catálogo */ + description?: string + }[] + } + RelatedResourceMessage: { + /** Tipo de recurso relacionado. */ + resource_type?: string + /** ID del recurso relacionado. */ + resource_id?: string + /** Origen del mensaje. */ + source?: string + /** + * Severidad del mensaje. + * @enum {string} + */ + severity?: 'error' | 'warning' | 'info' + /** Mensaje relacionado con el recurso. */ + message?: string + /** + * Format: date-time + * Fecha y hora de creación del mensaje. + */ + created_at?: Date | string + } + EventBase: { + /** ID del evento */ + id: string + /** + * Format: date-time + * Fecha y hora de creación del evento + */ + created_at: Date | string + /** Indica si el evento se generó en modo test (false) o en modo producción (true). */ + livemode: boolean + /** ID de la organización a la que pertenece el evento */ + organization: string + /** Mensajes relacionados con el recurso asociado al evento. */ + related_resource_messages?: components['schemas']['RelatedResourceMessage'][] + } + DateRange: { + /** + * Greater than + * Format: date-time + * Límite inferior exclusivo del rango de fechas a solicitar. + */ + gt?: Date | string + /** + * Greater than or equals + * Format: date-time + * Límite inferior inclusivo del rango de fechas a solicitar. + */ + gte?: Date | string + /** + * Lesser than + * Format: date-time + * Límite superior exclusivo del rango de fechas a solicitar. + */ + lt?: Date | string + /** + * Lesser than or equals + * Format: date-time + * Límite superior inclusivo del rango de fechas a solicitar. + */ + lte?: Date | string + } + GenericError: { + /** + * Descripción del error + * Indica qué salió mal y puede incluir una sugerencia sobre cómo solucionar el error. + */ + message: string + /** + * Código de estado HTTP + * Format: int32 + * Código de estado HTTP de esta respuesta de error. + */ + status: number + /** Indica si la petición fue exitosa. Siempre `false` en respuestas de error. */ + ok: boolean + /** Código de error estable para manejar el error de forma programática. Consulta la guía de manejo de errores para ver la lista de códigos documentados. */ + code: string + /** + * Ubicación opcional del dato relacionado con el error. + * @enum {string} + */ + location?: 'body' | 'query' | 'params' | 'headers' | 'files' + /** Ruta opcional del campo relacionado con el error. */ + path?: string + /** Detalles adicionales del error. Sólo se incluye cuando aporta información útil. */ + errors?: components['schemas']['ErrorDetail'][] + } + ErrorDetail: { + /** Mensaje legible del detalle. */ + message: string + /** Subcódigo del detalle. En validaciones de Facturapi usa códigos como `required`, `invalid_type` o `tax_id_not_found`; en errores externos puede contener el código original del proveedor. */ + code: string + /** + * Ubicación opcional del dato relacionado con este detalle. + * @enum {string} + */ + location?: 'body' | 'query' | 'params' | 'headers' | 'files' + /** Ruta opcional del campo relacionado con este detalle. */ + path?: string + /** + * Fuente del detalle. + * @enum {string} + */ + source: 'facturapi' | 'sat' | 'pac' + } + /** + * Indica si la factura fue emitida por tu organización o recibida de un tercero. + * @enum {string} + */ + IssuingType: 'issuing' | 'receiving' + /** + * Estado de la solicitud de cancelación de la factura. + * @enum {string} + */ + CancellationStatus: 'none' | 'accepted' | 'pending' | 'rejected' | 'expired' + SearchResult: { + /** + * Página + * Número de página. Vale 0 cuando no hay coincidencias. Se omite en todas las respuestas de paginación por cursor, incluida la primera página. + */ + page?: number + /** + * Páginas totales + * Total de páginas. Se omite en todas las respuestas de paginación por cursor, incluida la primera página. + */ + total_pages?: number + /** + * Resultados totales + * Número de elementos individuales en todas las páginas de resultados. En modo `pagination=cursor` solo se incluye en la primera página de la búsqueda (sin `after`/`before`); el total no cambia entre páginas. + */ + total_results?: number + /** + * Cursor anterior + * Cursor para obtener la página anterior de resultados. Es `null` en la primera página. Solo disponible con `pagination=cursor`. + */ + previous_cursor?: string | null + /** + * Cursor siguiente + * Cursor para obtener la página siguiente de resultados. Es `null` cuando no hay más resultados. Solo disponible con `pagination=cursor`. + */ + next_cursor?: string | null + /** + * Resultados con tope + * Indica si `total_results` está limitado a 3,000 porque existen más resultados de los reportados. + */ + totals_are_capped?: boolean + } + ResourceAutoGeneratedProps: { + /** ID del objeto */ + id: string + /** + * Format: date-time + * Fecha de registro + */ + created_at: Date | string + /** Si el valor es `true`, indica que el objeto fue creado en ambiente Live; o si es `false`, en ambiente Test. */ + livemode: boolean + } + TaxIdValidationResult: { + /** + * Resultado de la validación en la lista de Empresas que + * Facturan Operaciones Simuladas del SAT. + */ + efos?: { + /** + * Indica si el RFC tiene algún asunto relacionado con esta lista. + * `true`: El RFC no está en la lista de EFOS o su situación fue + * apelada y resultó favorable. `false`: El RFC está registrado como + * “Presunto” o “Definitivo” en la lista de EFOS. + */ + is_valid?: boolean + /** + * Objeto con el resultado de la búqueda ante el SAT. + * Toda la información contenida en este objeto proviene del SAT. + */ + data?: { + /** + * Disponible sólo cuando el RFC no fue encontrado en la lista, + * lo cual es bueno. + */ + mensaje?: string + /** Texto que indica la fecha de actualización de la lista. */ + fechaLista?: string + /** Arreglo con los resultados de la búsqueda en la lista de EFOS. */ + detalles?: { + /** El RFC consultado, a manera de confirmación. */ + rfc?: string + /** Razón social del contribuyente. */ + razonSocial?: string + /** + * Texto que indica la situación actual. Consulta + * [esta tabla](#situación-del-contribuyente) para ver + * el detalle de los distintos valores. + */ + situacionContribuyente?: string + /** Texto con identificador y fecha del reporte de presunción. */ + numFechaPresuncion?: string + /** + * Format: DD/MM/YYYY + * Fecha de publicación de presunción. + */ + pubFechaSatPresuntos?: string + /** Texto con identificador y fecha de publicación en el listado global de presunción. */ + numGlobalPresuncion?: string + /** + * Format: DD/MM/YYYY + * Fecha de publicación en el Diario Oficial de la Federación (DOF). + */ + pubFechaDofPresuntos?: string + /** Identificador de la publicación de estado “Definitivo”. */ + pubSatDefinitivos?: string + /** + * Format: DD/MM/YYYY + * Fecha de la publicación de estado “Definitivo” en el DOF. + */ + pubDofDefinitivos?: string + /** Texto con identificador y fecha de sentencia favorable. */ + numFechaSentFav?: string + /** + * Format: DD/MM/YYYY + * Fecha de sentencia favorable + */ + pubSatSentFav?: string + }[] + } + } + } + ProductCatalogResult: { + /** Clave del catálogo */ + key?: string + /** Descripción */ + description?: string + /** + * Número del 0 al 1 que representa el nivel de coincidencia del + * resultado con respecto a la consulta de búsqueda. + */ + score?: number + } + UnitCatalogResult: { + /** Clave del catálogo */ + key?: string + /** Descripción */ + description?: string + /** + * Número del 0 al 1 que representa el nivel de coincidencia del + * resultado con respecto a la consulta de búsqueda. + */ + score?: number + } + ProductCatalogSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['ProductCatalogResult'][] + } + UnitCatalogSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['UnitCatalogResult'][] + } + LocalTax: { + /** Tasa del impuesto en fracción decimal. */ + rate: number + /** Base del impuesto. Si se omite, se utiliza el subtotal completo del concepto. */ + base?: number + /** Nombre del impuesto. Texto libre. */ + type: string + /** + * Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + * @default false + */ + withholding?: boolean + /** @enum {string} */ + factor?: 'Tasa' | 'Cuota' | 'Exento' + } + /** Tax */ + BaseTax: { + /** Tasa del impuesto en fracción decimal. */ + rate: number + /** Base del impuesto. Si se omite, se calcula a partir del subtotal del concepto y el factor del impuesto. Para el factor Cuota, se utiliza la cantidad de unidades. */ + base?: number + /** + * Tipo de impuesto. + * @default IVA + * @enum {string} + */ + type?: 'IVA' | 'ISR' | 'IEPS' + ieps_mode?: components['schemas']['IepsMode'] + /** + * Tipo factor + * @default Tasa + * @enum {string} + */ + factor?: 'Tasa' | 'Cuota' | 'Exento' + /** + * Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + * @default false + */ + withholding?: boolean + } + /** + * Indica la manera de cobrar el impuesto, y puede tener los valores: + * + * `"sum_before_taxes"`: Aplica primero el IEPS al subtotal y usa el resultado como base del resto de impuestos en el producto. + * + * `"break_down"`: Cobra y desglosa el IEPS al mismo nivel que el resto de los impuestos en el producto. + * + * `"unit"`: Aplica el IEPS antes del precio unitario, y usa el precio unitario original como base para el resto de impuestos. + * + * `"subtract_before_break_down"`: Aplica el IEPS solo para calcular impuestos como IVA de traslado y retenciones, y usa el precio unitario original como base para el resto de impuestos. + * + * Consulta con tu contador qué caso aplica para tu giro de empresa y producto. + * @default sum_before_taxes + * @enum {string} + */ + IepsMode: + 'sum_before_taxes' | 'break_down' | 'unit' | 'subtract_before_break_down' + IepsTax: Omit & { + /** @constant */ + type: 'IEPS' + ieps_mode?: components['schemas']['IepsMode'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'IEPS' + } + /** Información sobre el timbre fiscal digital agregado por el PAC. */ + Stamp: { + /** Sello digital del comprobante fiscal. */ + signature?: string + /** FechaTimbrado del SAT: fecha y hora local sin offset de zona horaria. Se conserva como texto. */ + date?: string + /** Número de serie del certificado del SAT usado para timbrar. */ + sat_cert_number?: string + /** Sello digital del timbre fiscal digital. */ + sat_signature?: string + } + LineItem: { + /** Cuentas prediales de este concepto. */ + property_tax_account?: string[] + /** Cantidad de unidades incluidas del mismo concepto. */ + quantity?: number + /** Monto total de descuento aplicado a este concepto. */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product?: components['schemas']['LineItemProduct'] + /** Objeto con información de las partes de la factura. */ + parts?: components['schemas']['Parts'][] + } + /** + * Objeto con información del contribuyente tercero, a cuenta del que se realiza la operación. + * + * Corresponde al campo "ACuentaTerceros" en el CFDI. + */ + ThirdParty: { + /** Nombre o razón social del tercero. */ + legal_name?: string + /** RFC del tercero. */ + tax_id?: string + /** Régimen fiscal del tercero. */ + tax_system?: string + /** Código postal del tercero. */ + zip?: string + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** + * Monto total de descuento aplicado a este concepto. + * @default 0 + */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemProductInput'] | string + parts?: components['schemas']['PartInput'][] + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** Código XML de tu complemento concepto, el complemento Hidrocarburos y Petrolíferos o el complemento Instituciones Educativas Privadas. */ + complement?: + | string + | components['schemas']['HidroYPetroComplementInput'] + | components['schemas']['IeduComplementInput'] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Números de cuenta para el impuesto predial. */ + property_tax_account?: string[] + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemEgresoInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** + * Monto total de descuento aplicado a este concepto. + * @default 0 + */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemProductEgresoInput'] | string + parts?: components['schemas']['PartInput'][] + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** Código XML de tu complemento concepto, el complemento Hidrocarburos y Petrolíferos o el complemento Instituciones Educativas Privadas. */ + complement?: + | string + | components['schemas']['HidroYPetroComplementInput'] + | components['schemas']['IeduComplementInput'] + third_party?: Record & + components['schemas']['ThirdParty'] + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemTrasladoInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemTrasladoProductInput'] | string + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** + * Format: xml + * Código XML de tu complemento concepto. + */ + complement?: string + parts?: components['schemas']['PartInput'][] + third_party?: { + /** Nombre o razón social del tercero. */ + legal_name: string + /** RFC del tercero. */ + tax_id: string + /** Régimen fiscal del tercero. */ + tax_system: string + /** Código postal del tercero. */ + zip: string + } + } + /** HidroYPetroComplement */ + HidroYPetroComplementInput: { + /** + * Tipo de permiso otorgado por la autoridad competente, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * @enum {string} + */ + tipo_permiso: + | 'PER01' + | 'PER02' + | 'PER03' + | 'PER04' + | 'PER05' + | 'PER06' + | 'PER07' + | 'PER08' + | 'PER09' + | 'PER10' + | 'PER11' + /** Número de permiso otorgado por la autoridad competente, conforme a la nomenclatura del catálogo c_TipoPermiso. */ + numero_permiso: string + /** + * Subtipo del hidrocarburo o petrolífero, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * @enum {string} + */ + sub_producto_hyp: + | 'SP16' + | 'SP17' + | 'SP18' + | 'SP19' + | 'SP22' + | 'SP23' + | 'SP24' + | 'SP25' + | 'SP48' + /** + * Clave correspondiente a hidrocarburos y petrolíferos, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * + * Puedes enviarla explícitamente o dejar que Facturapi la derive desde el `product_key` del concepto cuando aplique. + * @enum {string} + */ + clave_hyp?: '15101514' | '15101515' | '15101505' + } + /** + * IeduComplement + * Complemento concepto de Instituciones Educativas Privadas versión 1.0. + * + * Se incluye a nivel concepto dentro de `items[].complement`. + */ + IeduComplementInput: { + /** Nombre del alumno. */ + nombreAlumno: string + /** CURP del alumno de la institución educativa. */ + CURP: string + /** + * Nivel educativo que cursa el alumno. + * @enum {string} + */ + nivelEducativo: + | 'Preescolar' + | 'Primaria' + | 'Secundaria' + | 'Profesional técnico' + | 'Bachillerato o su equivalente' + /** Clave del centro de trabajo o reconocimiento de validez oficial de estudios de la institución educativa privada donde se realiza el pago. */ + autRVOE: string + /** RFC de quien realiza el pago cuando sea diferente a quien recibe el servicio. */ + rfcPago?: string + } + /** + * string + * Format: xml + * Código XML de tu complemento tal cual como quieres que se inserte en el XML. Debe contener solamente un nodo XML raíz. + */ + CustomComplementData: string + /** CustomComplement */ + CustomComplementProperties: { + /** + * Tipo de complemento. (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: 'custom' + data: components['schemas']['CustomComplementData'] + } + /** CustomComplement */ + CustomComplementInput: components['schemas']['CustomComplementProperties'] & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'custom' + } + /** + * NominaComplementData + * Objeto con la información del complemento de nómina. + */ + NominaComplementDataInput: WithRequired< + components['schemas']['NominaComplementDataDirectProperties'], + 'fecha_inicial_pago' | 'fecha_final_pago' | 'num_dias_pagados' + > & + WithRequired< + components['schemas']['NominaComplementDataNestedInput'], + 'receptor' | 'percepciones' + > + /** Complemento de Nómina. */ + NominaComplementDataProperties: components['schemas']['NominaComplementDataDirectProperties'] & + components['schemas']['NominaComplementDataNestedProperties'] + NominaComplementDataDirectProperties: { + /** + * Tipo de nómina. + * - `“O”` (Ordinaria): Cuando corresponde a un pago que se realiza de manera habitual, como sueldos. + * - `“E”` (Extraordinaria): Para pagos fuera de lo habitual, como liquidaciones, aguinaldos o bonos. + * @default O + * @enum {string} + */ + tipo_nomina?: 'O' | 'E' + /** Fecha de pago de la nómina al trabajador. Si se omite, se utiliza la fecha y hora actuales. */ + fecha_pago?: components['schemas']['DateOrDateTime'] + /** Fecha inicial del periodo de pago. */ + fecha_inicial_pago?: components['schemas']['DateOrDateTime'] + /** Fecha final del periodo de pago. */ + fecha_final_pago?: components['schemas']['DateOrDateTime'] + /** Número de días pagados. Puede ser entero o fracción. */ + num_dias_pagados?: number + } + NominaComplementDataNestedInput: { + emisor?: components['schemas']['NominaEmisorInput'] + receptor?: components['schemas']['NominaReceptorInput'] + percepciones?: components['schemas']['NominaPercepcionesInput'] + /** Arreglo de objetos donde se expresan las deducciones aplicables. */ + deducciones?: components['schemas']['NominaDeduccionInput'][] + /** Arreglo de objetos para expresar otros pagos aplicables. */ + otros_pagos?: (components['schemas']['NominaOtroPagoInput'] & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionInput'] + })[] + /** Arreglo de objetos con información de incapacidades. */ + incapacidades?: components['schemas']['NominaIncapacidadInput'][] + } + NominaComplementDataNestedProperties: { + emisor?: components['schemas']['NominaEmisorProperties'] + receptor?: components['schemas']['NominaReceptorProperties'] + percepciones?: components['schemas']['NominaPercepcionesProperties'] + /** Arreglo de objetos donde se expresan las deducciones aplicables. */ + deducciones?: components['schemas']['NominaDeduccionProperties'][] + /** Arreglo de objetos para expresar otros pagos aplicables. */ + otros_pagos?: (components['schemas']['NominaOtroPagoDirectProperties'] & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionProperties'] + })[] + /** Arreglo de objetos con información de incapacidades. */ + incapacidades?: components['schemas']['NominaIncapacidadProperties'][] + } + /** Incapacidad */ + NominaIncapacidadInput: WithRequired< + components['schemas']['NominaIncapacidadProperties'], + 'dias_incapacidad' | 'tipo_incapacidad' + > + NominaIncapacidadProperties: { + /** Número de días enteros que el trabajador se incapacitó en el periodo. */ + dias_incapacidad?: number + /** Clave del catálogo [Tipo de Incapacidad](#tipo-de-incapacidad). */ + tipo_incapacidad?: string + /** Monto del importe monetario de la incapacidad. */ + importe_monetario?: number + } + /** OtroPago */ + NominaOtroPagoInput: WithRequired< + components['schemas']['NominaOtroPagoDirectProperties'], + 'tipo_otro_pago' | 'clave' | 'importe' + > & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionInput'] + } + NominaOtroPagoDirectProperties: { + /** Clave del catálogo [Tipo de Otro Pago](#tipo-de-otro-pago). */ + tipo_otro_pago?: string + /** Clave de otro pago de nómina propia de la contabilidad de cada patrón. */ + clave?: string + /** Descripción alternativa correspondiente a la clave utilizada. */ + concepto?: string + /** Importe por concepto de otro pago. */ + importe?: number + /** + * Subsidio causado conforme a la tabla del subsidio para el empleo + * publicada en el Anexo 8 de la Resolución Miscelánea Fiscal vigente. + * + * Este valor será insertado dentro del nodo `SubsidioAlEmpleo`, y es + * requerido cuando el valor de `tipo_otro_pago` es `"002"`. + */ + subsidio_causado?: number + } + NominaCompensacionInput: WithRequired< + components['schemas']['NominaCompensacionProperties'], + 'saldo_a_favor' | 'ano' | 'remanente_sal_fav' + > + /** Objeto con información referente a la compensación de saldos a favor de un trabajador. */ + NominaCompensacionProperties: { + /** Monto por saldo a favor determinado por el patrón al trabajador en periodos o ejercicios anteriores. */ + saldo_a_favor?: number + /** Año en que se determinó el saldo a favor del trabajador. */ + ano?: number + /** Remanente del saldo a favor del trabajador. */ + remanente_sal_fav?: number + } + /** Deduccion */ + NominaDeduccionInput: WithRequired< + components['schemas']['NominaDeduccionProperties'], + 'tipo_deduccion' | 'clave' | 'importe' + > + NominaDeduccionProperties: { + /** Clave del catálogo [Tipo de deducción](#tipo-de-deducción). */ + tipo_deduccion?: string + /** Concepto de la deducción. Si no se envía, se utilizará la descripción del catálogo del tipo de deducción. */ + concepto?: string + /** Clave de control interno que asigna el patrón a cada deducción (descuento) de nómina propia de su contabilidad. */ + clave?: string + /** Importe del concepto de deducción. */ + importe?: number + } + /** + * Percepciones + * Objeto para indicar las percepciones aplicables. + */ + NominaPercepcionesInput: { + /** Objeto con información detallada de cada percepción. */ + percepcion: components['schemas']['NominaPercepcionInput'][] + jubilacion_pension_retiro?: components['schemas']['NominaJubilacionInput'] + separacion_indemnizacion?: components['schemas']['NominaSeparacionInput'] + } + /** + * Percepciones + * Objeto para indicar las percepciones aplicables. + */ + NominaPercepcionesProperties: { + /** Objeto con información detallada de cada percepción. */ + percepcion?: components['schemas']['NominaPercepcionProperties'][] + jubilacion_pension_retiro?: components['schemas']['NominaJubilacionProperties'] + separacion_indemnizacion?: components['schemas']['NominaSeparacionProperties'] + } + /** Separacion */ + NominaSeparacionInput: WithRequired< + components['schemas']['NominaSeparacionProperties'], + | 'total_pagado' + | 'num_anos_servicio' + | 'ultimo_sueldo_mens_ord' + | 'ingreso_acumulable' + | 'ingreso_no_acumulable' + > + /** + * Jubilacion + * Objeto con información detallada de pagos por separación (despido) o indemnización. + */ + NominaSeparacionProperties: { + /** Monto total pagado por concepto de separación o indemnización. */ + total_pagado?: number + /** Años de servicio que laboró el trabajador, redondeado al entero inmediato superior. */ + num_anos_servicio?: number + /** Último sueldo mensual ordinario percibido por el trabajador. */ + ultimo_sueldo_mens_ord?: number + /** Monto por ingresos acumulables. */ + ingreso_acumulable?: number + /** Monto por ingresos no acumulables. */ + ingreso_no_acumulable?: number + } + /** Jubilacion */ + NominaJubilacionInput: WithRequired< + components['schemas']['NominaJubilacionProperties'], + 'ingreso_acumulable' | 'ingreso_no_acumulable' + > + /** Objeto con información detallada de pagos por jubilación, pensiones o haberes de retiro. */ + NominaJubilacionProperties: { + /** Monto total del pago entregado en una sola exhibición. */ + total_una_exhibicion?: number + /** Monto total del pago entregado en parcialidades. */ + total_parcialidad?: number + /** Monto diario percibido por el trabajador cuando el pago se realiza en parcialidades. */ + monto_diario?: number + /** Ingresos acumulables percibidos por el trabajador. */ + ingreso_acumulable?: number + /** Ingresos no acumulables percibidos por el trabajador. */ + ingreso_no_acumulable?: number + } + /** Percepcion */ + NominaPercepcionProperties: components['schemas']['NominaPercepcionDirectProperties'] & + components['schemas']['NominaPercepcionNestedProperties'] + /** + * Percepcion + * La entrada utiliza las claves de percepción del catálogo publicado. La clave 019 requiere horas_extra. + */ + NominaPercepcionInput: (WithRequired< + components['schemas']['NominaPercepcionDirectProperties'], + 'tipo_percepcion' | 'clave' | 'importe_gravado' | 'importe_exento' + > & + components['schemas']['NominaPercepcionNestedInput']) & + ( + | { + /** @constant */ + tipo_percepcion?: '019' + horas_extra: components['schemas']['NominaHorasExtraInput'][] + } + | { + /** @enum {string} */ + tipo_percepcion?: + | '001' + | '002' + | '003' + | '004' + | '005' + | '006' + | '009' + | '010' + | '011' + | '012' + | '013' + | '014' + | '015' + | '020' + | '021' + | '022' + | '023' + | '024' + | '025' + | '026' + | '027' + | '028' + | '029' + | '030' + | '031' + | '032' + | '033' + | '034' + | '035' + | '036' + | '037' + | '038' + | '039' + | '044' + | '045' + | '046' + | '047' + | '048' + | '049' + | '050' + | '051' + | '052' + | '053' + | '054' + | '055' + | '056' + } + ) + NominaPercepcionDirectProperties: { + /** Clave del catálogo [Tipo de percepción](#tipo-de-percepcion). */ + tipo_percepcion?: string + /** Concepto de la percepción. Si no se envía, se utilizará la descripción del catálogo del tipo de percepción. */ + concepto?: string + /** Clave de control interno que asigna el patrón a cada percepción de nómina propia de su contabilidad. */ + clave?: string + /** Importe gravado por el concepto indicado en el tipo de percepción. */ + importe_gravado?: number + /** Importe exento por el concepto indicado en el tipo de percepción. */ + importe_exento?: number + } + NominaPercepcionNestedInput: { + acciones_o_titulos?: components['schemas']['NominaAccionesInput'] + /** Arreglo de objetos para expresar las horas extra aplicables. Requerido cuando el tipo de percepción es “019” (Horas extras). */ + horas_extra?: components['schemas']['NominaHorasExtraInput'][] + } + NominaPercepcionNestedProperties: { + acciones_o_titulos?: components['schemas']['NominaAccionesProperties'] + /** Arreglo de objetos para expresar las horas extra aplicables. Requerido cuando el tipo de percepción es “019” (Horas extras). */ + horas_extra?: components['schemas']['NominaHorasExtraProperties'][] + } + /** HorasExtra */ + NominaHorasExtraInput: WithRequired< + components['schemas']['NominaHorasExtraProperties'], + 'dias' | 'tipo_horas' | 'horas_extra' | 'importe_pagado' + > + /** HorasExtra */ + NominaHorasExtraProperties: { + /** Número de días en que el trabajador laboró horas extra adicionales a su jornada normal de trabajo. */ + dias?: number + /** Clave del catálogo [Tipo de Horas](#tipo-de-Horas). */ + tipo_horas?: string + /** Número de horas extra trabajadas en el periodo. */ + horas_extra?: number + /** Importe pagado por las horas extra. */ + importe_pagado?: number + } + /** Accion */ + NominaAccionesInput: WithRequired< + components['schemas']['NominaAccionesProperties'], + 'valor_mercado' | 'precio_al_otorgarse' + > + /** + * Accion + * Objeto para expresar ingresos por acciones o títulos valor que representan bienes. Es requerido cuando existan ingresos por sueldos derivados de adquisición de acciones o títulos. + */ + NominaAccionesProperties: { + /** Valor de mercado de las Acciones o Títulos valor al ejercer la opción. */ + valor_mercado?: number + /** Precio establecido al otorgarse la opción de ingresos en acciones o títulos valor. */ + precio_al_otorgarse?: number + } + /** + * Receptor + * Información del trabajador. + */ + NominaReceptorProperties: components['schemas']['NominaReceptorDirectProperties'] & + components['schemas']['NominaReceptorNestedProperties'] + /** + * Receptor + * Información del trabajador. + */ + NominaReceptorInput: WithRequired< + components['schemas']['NominaReceptorDirectProperties'], + | 'curp' + | 'tipo_contrato' + | 'tipo_regimen' + | 'num_empleado' + | 'periodicidad_pago' + | 'clave_ent_fed' + > & + components['schemas']['NominaReceptorNestedInput'] + NominaReceptorDirectProperties: { + /** CURP del trabajador. */ + curp?: string + /** Número de seguridad social. */ + num_seguridad_social?: string + /** Fecha de inicio de la relación laboral entre el empleador y el empleado. */ + fecha_inicio_rel_laboral?: components['schemas']['DateOrDateTime'] + /** + * Antigüedad del empleado en el formato especificado por el SAT. Si se envía un `string`, se espera que éste contenga la antigüedad en el formato que especifica el SAT. Si se envía el valor booleano `false`, este campo no se incluirá en la factura. Si se envía el valor booleano `true` y `fecha_inicio_rel_laboral` existe, este valor se calculará con la diferencia entre la fecha de inicio de relación laboral y la fecha de pago. + * @default true + */ + antiguedad?: string | boolean + /** Clave del catálogo del SAT [Tipo de Contrato](#tipo-de-contrato). */ + tipo_contrato?: string + /** + * Indica si el trabajador está asociado a un sindicato. + * @default false + */ + sindicalizado?: boolean + /** Clave del catálogo del SAT [Tipo de Jornada](#tipo-de-jornada). */ + tipo_jornada?: string + /** Clave del catálogo del SAT [Tipo de Régimen](#régimen-fiscal). */ + tipo_regimen?: string + /** Número interno de empleado, asignado por el empleador. */ + num_empleado?: string + /** Nombre del departamento o área a la que pertenece el trabajador. */ + departamento?: string + /** Nombre del puesto asignado al empleado o el nombre de la actividad que realiza. */ + puesto?: string + /** Clave del catálogo del SAT [Riesgo del Puesto](#riesgo-del-puesto). */ + riesgo_puesto?: string + /** Clave del catálogo del SAT [Periodicidad de Pago](#periodicidad-del-pago). */ + periodicidad_pago?: string + /** Clave del banco de acuerdo al catálogo del SAT “Bancos” que puedes consultar utilizando nuestra [herramienta de búsqueda](https://dashboard.facturapi.io/catalogs/bank). */ + banco?: string + /** Número de cuenta bancaria (11 caracteres) o número de teléfono celular (10 caracteres) o número de tarjeta (15 ó 16 caracteres) o la CLABE (18 caracteres) o número de monedero electrónico donde se realiza el depósito de nómina. */ + cuenta_bancaria?: string + /** Importe de la retribución en efectivo por cuota diaria, gratificaciones, percepciones, alimentación, habitación, primas, comisiones, prestaciones en especie, etc. */ + salario_base_cot_apor?: number + /** Salario que se integra con los pagos hechos en efectivo por cuota diaria, gratificaciones, percepciones, habitación, primas, comisiones, prestaciones en especie y cualquier otra cantidad o prestación que se entregue al trabajador por su trabajo. */ + salario_diario_integrado?: number + /** Clave de la entidad federativa en donde el trabajador prestó sus servicios al empleador, que puedes consultar utilizando nuestra [herramienta de búsqueda](https://dashboard.facturapi.io/catalogs/state). */ + clave_ent_fed?: string + } + NominaReceptorNestedProperties: { + /** Arreglo de objetos para expresar información sobre la empresa que se beneficia del trabajo del empleado, en casos donde el emisor preste servicios de subcontratación. */ + sub_contratacion?: components['schemas']['NominaSubContratacionProperties'][] + } + NominaReceptorNestedInput: { + /** Arreglo de objetos para expresar información sobre la empresa que se beneficia del trabajo del empleado, en casos donde el emisor preste servicios de subcontratación. */ + sub_contratacion?: (components['schemas']['NominaSubContratacionRequiredProperties'] & + components['schemas']['NominaSubContratacionProperties'])[] + } + NominaSubContratacionRequiredProperties: Record + NominaSubContratacionProperties: { + /** RFC de la persona o empresa que subcontrata, es decir, de la persona o empresa en donde el trabajador prestó directamente sus servicios. */ + rfc_labora?: string + /** Porcentaje de tiempo en que el trabajador prestó sus servicios a la persona o empresa que lo subcontrató. */ + porcentaje_tiempo?: number + } + NominaEntidadSncfInput: { + /** @enum {string} */ + origen_recurso: 'IP' | 'IF' | 'IM' + monto_recurso_propio?: number + } & ( + | { + /** @constant */ + origen_recurso?: 'IM' + monto_recurso_propio: number + } + | { + /** @enum {string} */ + origen_recurso?: 'IP' | 'IF' + } + ) + NominaEmisorInput: components['schemas']['NominaEmisorProperties'] & { + entidad_sncf?: components['schemas']['NominaEntidadSncfInput'] + } + /** + * Emisor + * Información del emisor, en caso de ser requerida. + */ + NominaEmisorProperties: { + /** Requerido cuando el empleador es persona física. CURP del empleador. */ + curp?: string + /** Clave de registro patronal asignada por la institución de seguridad social al patrón. */ + registro_patronal?: string + /** RFC de la persona que fungió como patrón. Se usa cuando el pago se realiza a través de un tercero. */ + rfc_patron_origen?: string + /** Información para que las entidades adheridas al Sistema Nacional de Coordinación Fiscal realicen la identificación del origen de los recursos. */ + entidad_sncf?: { + /** + * Clave de origen de recurso. + * + * - `“IP”`: Ingresos Propios + * - `“IF”`: Ingresos Federales + * - `“IM”`: Ingresos mixtos. + * @enum {string} + */ + origen_recurso?: 'IP' | 'IF' | 'IM' + /** Importe de recursos propios. Requerido cuando el origen del recurso es por ingresos mixtos. */ + monto_recurso_propio?: number + } + } + /** Complement */ + PagoOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: 'pago' | 'custom' + } & ( + | components['schemas']['PagoComplementProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + PagoOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'pago' | 'custom' + } & ( + | components['schemas']['PagoComplementInput'] + | components['schemas']['CustomComplementInput'] + ) + PagoComplementProperties: { + /** @constant */ + type: 'pago' + } & { + data?: components['schemas']['PagoComplementDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'pago' + } + PagoComplementInput: { + /** @constant */ + type: 'pago' + } & { + data?: components['schemas']['PagoComplementDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'pago' + } + InvoiceComplementInput: + | components['schemas']['PagoComplementInput'] + | components['schemas']['NominaComplementInput'] + | components['schemas']['CartaPorteInput'] + | components['schemas']['ComercioExteriorInput'] + | components['schemas']['LeyendasFiscalesInput'] + | components['schemas']['CustomComplementInput'] + InvoiceComplementProperties: + | components['schemas']['PagoComplementProperties'] + | components['schemas']['NominaComplementProperties'] + | components['schemas']['CartaPorteProperties'] + | components['schemas']['ComercioExteriorProperties'] + | components['schemas']['LeyendasFiscalesProperties'] + | components['schemas']['CustomComplementProperties'] + PagoComplementDataProperties: components['schemas']['PaymentProperties'][] + PaymentProperties: components['schemas']['PaymentInput'] & { + /** Format: date-time */ + date: Date | string + } + /** + * PagoComplementData + * Pagos a incluir en este comprobante. Lo más común es incluir un sólo pago. Un caso en el que se debe de agregar más de uno es cuando el pago se realiza con 2 formas de pago distintas; por ejemplo, cuando se paga una parte con tarjeta y otra en efectivo. + */ + PagoComplementDataInput: + | components['schemas']['PaymentInput'] + | components['schemas']['PaymentInput'][] + /** Complement */ + NominaOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: 'nomina' | 'custom' + } & ( + | components['schemas']['NominaComplementProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + NominaOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'nomina' | 'custom' + } & ( + | components['schemas']['NominaComplementInput'] + | components['schemas']['CustomComplementInput'] + ) + NominaComplementProperties: { + /** @constant */ + type: 'nomina' + } & { + data?: components['schemas']['NominaComplementDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'nomina' + } + NominaComplementInput: { + /** @constant */ + type: 'nomina' + } & { + data?: components['schemas']['NominaComplementDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'nomina' + } + CartaPorteProperties: { + /** @constant */ + type: 'carta_porte' + } & { + data?: components['schemas']['CartaPorteDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'carta_porte' + } + CartaPorteInput: { + /** @constant */ + type: 'carta_porte' + } & { + data?: components['schemas']['CartaPorteDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'carta_porte' + } + ComercioExteriorProperties: { + /** @constant */ + type: 'comercio_exterior' + } & { + data?: components['schemas']['ComercioExteriorDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'comercio_exterior' + } + ComercioExteriorInput: { + /** @constant */ + type: 'comercio_exterior' + } & { + data?: components['schemas']['ComercioExteriorDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'comercio_exterior' + } + LeyendasFiscalesProperties: { + /** @constant */ + type: 'leyendas_fiscales' + } & { + data?: components['schemas']['LeyendasFiscalesData'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'leyendas_fiscales' + } + LeyendasFiscalesInput: { + /** @constant */ + type: 'leyendas_fiscales' + } & { + data?: components['schemas']['LeyendasFiscalesData'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'leyendas_fiscales' + } + /** Complement */ + CartaPorteOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: + 'carta_porte' | 'comercio_exterior' | 'leyendas_fiscales' | 'custom' + } & ( + | components['schemas']['CartaPorteProperties'] + | components['schemas']['ComercioExteriorProperties'] + | components['schemas']['LeyendasFiscalesProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + CartaPorteOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'carta_porte' | 'comercio_exterior' | 'leyendas_fiscales' | 'custom' + } & ( + | components['schemas']['CartaPorteInput'] + | components['schemas']['ComercioExteriorInput'] + | components['schemas']['LeyendasFiscalesInput'] + | components['schemas']['CustomComplementInput'] + ) + /** + * LeyendasFiscales + * Complemento de Leyendas Fiscales versión 1.0. + */ + LeyendasFiscalesData: { + /** Leyendas fiscales a incluir en el comprobante. */ + leyendas: { + /** Disposición fiscal aplicable a la leyenda. */ + disposicion_fiscal?: string + /** Norma que regula la leyenda. */ + norma?: string + /** Texto de la leyenda fiscal. */ + texto_leyenda: string + }[] + } + /** + * CartaPorte + * Complemento Carta Porte versión 3.1. (Beta) + */ + CartaPorteDataProperties: { + /** Identificador único de la Carta Porte. */ + IdCCP: string + /** Indica si el transporte es internacional. */ + TranspInternac: string + /** Entrada o salida de mercancías. */ + EntradaSalidaMerc?: string + /** País de origen o destino. */ + PaisOrigenDestino?: string + /** Vía de entrada o salida. */ + ViaEntradaSalida?: string + /** Distancia total recorrida. */ + TotalDistRec?: number + /** Registro del programa ISTMO. */ + RegistroISTMO?: string + /** Polo origen. */ + UbicacionPoloOrigen?: string + /** Polo destino. */ + UbicacionPoloDestino?: string + /** Objeto con los regímenes aduaneros aplicables. */ + RegimenesAduaneros?: Record + /** Arreglo de ubicaciones. */ + Ubicaciones: { + /** Atributo requerido para precisar si el tipo de ubicación corresponde al origen o destino de las ubicaciones para el traslado de los bienes y/o mercancías en los distintos medios de transporte. Valores: "Origen" | "Destino". */ + TipoUbicacion: string + /** Atributo condicional para registrar una clave que identifique el punto de salida o entrada de los bienes y/o mercancías. Formato: "OR" o "DE" seguido de 6 dígitos numéricos (expresión regular (OR|DE)[0-9]{6}). */ + IDUbicacion?: string + /** Atributo requerido para registrar el RFC del remitente o destinatario de los bienes y/o mercancías que se trasladan. */ + RFCRemitenteDestinatario: string + /** Atributo opcional para registrar el nombre del remitente o destinatario de los bienes y/o mercancías (longitud 1 a 254 caracteres). */ + NombreRemitenteDestinatario?: string + /** Atributo condicional para el número de identificación o registro fiscal del país de residencia del remitente o destinatario cuando se trate de residentes en el extranjero (longitud 6 a 40 caracteres). */ + NumRegIdTrib?: string + /** Atributo condicional para registrar la clave del país de residencia fiscal conforme al catálogo c_Pais (ISO 3166-1). */ + ResidenciaFiscal?: string + /** Atributo condicional para la clave de la estación de origen o destino conforme al catálogo c_Estaciones del complemento Carta Porte y al tipo de transporte. */ + NumEstacion?: string + /** Atributo condicional para el nombre de la estación de origen o destino conforme al catálogo c_Estaciones (longitud 1 a 50 caracteres). */ + NombreEstacion?: string + /** Atributo condicional para registrar el tipo de puerto de origen o destino en transporte marítimo. Valores: "Altura" | "Cabotaje". */ + NavegacionTrafico?: string + /** Atributo requerido para registrar la fecha y hora estimada de salida o llegada en formato AAAA-MM-DDThh:mm:ss. */ + FechaHoraSalidaLlegada: string + /** Atributo condicional para registrar el tipo de estación por la que pasan las mercancías conforme al catálogo c_TipoEstacion. */ + TipoEstacion?: string + /** Atributo condicional para registrar en kilómetros la distancia recorrida entre la ubicación de origen y la de destino parcial o final. */ + DistanciaRecorrida?: number + Domicilio?: components['schemas']['CartaPorteDomicilio'] + }[] + Mercancias: components['schemas']['CartaPorteMercancias'] + /** Figuras de transporte. */ + FiguraTransporte?: { + /** Atributo requerido. Clave que identifica el tipo de figura de transporte conforme al catálogo correspondiente (operador, propietario, arrendatario, notificado). Debe coincidir con c_TipoFigura. */ + TipoFigura: string + /** RFC del operador/propietario/arrendatario o figura interveniente. */ + RFCFigura?: string + /** Número de licencia del operador cuando TipoFigura corresponde a operador. */ + NumLicencia?: string + /** Nombre o razón social de la figura de transporte (requerido). */ + NombreFigura: string + /** Número de registro fiscal en el extranjero de la figura cuando aplica. */ + NumRegIdTribFigura?: string + /** Clave del país de residencia fiscal de la figura (c_Pais) cuando es extranjero. */ + ResidenciaFiscalFigura?: string + /** Arreglo opcional con las partes del transporte que se relacionan a la figura. */ + PartesTransporte?: { + /** Clave de la parte del transporte conforme al catálogo c_ParteTransporte. */ + ParteTransporte: string + }[] + /** Domicilio asociado a la figura del transporte. */ + Domicilio?: components['schemas']['CartaPorteDomicilio'] + }[] + } + CartaPorteDataInput: components['schemas']['CartaPorteDataProperties'] + /** + * ComercioExterior + * Complemento Comercio Exterior versión 2.0. + */ + ComercioExteriorDataProperties: { + /** + * @default 2.0 + * @enum {string} + */ + Version?: '2.0' + /** Clave del catálogo c_MotivoTraslado. */ + MotivoTraslado?: string + /** Clave del pedimento (catálogo c_ClavePedimento). */ + ClaveDePedimento: string + /** + * Indica si existe certificado de origen. + * @enum {integer} + */ + CertificadoOrigen: 0 | 1 + /** Número de certificado de origen. */ + NumCertificadoOrigen?: string + /** Número de exportador confiable. */ + NumeroExportadorConfiable?: string + /** Clave del INCOTERM (catálogo c_INCOTERM). */ + Incoterm?: string + Observaciones?: string + /** Tipo de cambio USD. */ + TipoCambioUSD: number + /** Total en USD. */ + TotalUSD: number + /** Objeto con información del emisor del complemento. Requerido cuando el domicilio y CURP del emisor no se toman de la organización que emite el complemento. */ + Emisor?: components['schemas']['ComercioExteriorEmisor'] | boolean + Propietario?: ( + | components['schemas']['ComercioExteriorPropietario'] + | components['schemas']['CustomerComercioExterior'] + )[] + Receptor?: + | components['schemas']['ComercioExteriorReceptor'] + | components['schemas']['CustomerComercioExterior'] + Destinatario?: ( + | components['schemas']['ComercioExteriorDestinatario'] + | components['schemas']['CustomerComercioExterior'] + )[] + Mercancias: components['schemas']['ComercioExteriorMercancias'] + } + ComercioExteriorDataInput: components['schemas']['ComercioExteriorDataProperties'] + ComercioExteriorDomicilio: { + Calle: string + NumeroExterior?: string + NumeroInterior?: string + Colonia?: string + Localidad?: string + Referencia?: string + Municipio?: string + Estado: string + /** Clave del catálogo c_Pais. */ + Pais: string + CodigoPostal: string + } + ComercioExteriorEmisor: { + Domicilio: components['schemas']['ComercioExteriorDomicilio'] + Curp?: string + } + ComercioExteriorPropietario: { + NumRegIdTrib: string + /** Clave del catálogo c_Pais. */ + ResidenciaFiscal: string + } + ComercioExteriorReceptor: { + Domicilio?: components['schemas']['ComercioExteriorDomicilio'] + NumRegIdTrib?: string + } + ComercioExteriorDestinatario: { + Domicilio: components['schemas']['ComercioExteriorDomicilio'][] + NumRegIdTrib?: string + Nombre?: string + } + ComercioExteriorDescripcionesEspecificas: { + Marca: string + Modelo?: string + SubModelo?: string + NumeroSerie?: string + } + ComercioExteriorMercancia: { + DescripcionesEspecificas?: components['schemas']['ComercioExteriorDescripcionesEspecificas'][] + NoIdentificacion: string + /** Clave del catálogo c_FraccionArancelaria. */ + FraccionArancelaria?: string + CantidadAduana?: number + /** Clave del catálogo c_UnidadAduana. */ + UnidadAduana?: string + ValorUnitarioAduana?: number + ValorDolares: number + } + ComercioExteriorMercancias: { + Mercancia: components['schemas']['ComercioExteriorMercancia'][] + } + CartaPorteCantidadTransporta: { + Cantidad: number + IDOrigen: string + IDDestino: string + /** Clave del medio de transporte. */ + CvesTransporte?: string + } + CartaPorteDetalleMercancia: { + /** Clave de la unidad de peso de la mercancía conforme al catálogo correspondiente. */ + UnidadPesoMerc: string + /** Peso bruto de la mercancía incluyendo embalajes y tare. */ + PesoBruto: number + /** Peso neto de la mercancía sin incluir embalajes ni tara. */ + PesoNeto: number + /** Peso de la tara (contenedores, embalajes) asociado a la mercancía. */ + PesoTara: number + /** Número de piezas que conforman la mercancía detallada. */ + NumPiezas?: number + } + /** RFC del importador cuando aplica. */ + CartaPorteDocumentacionAduanera: { + /** Tipo de documento aduanero (pedimento, guía, conocimiento) relacionado. */ + TipoDocumento?: string + /** Número de pedimento de importación/exportación. */ + NumPedimento?: string + /** Identificador alterno del documento aduanero. */ + IdentDocAduanero?: string + RFCImpo?: string + } + CartaPorteGuiaIdentificacion: { + /** Número de la guía de identificación asociada a la mercancía. */ + NumeroGuiaIdentificacion?: string + /** Descripción detallada de la guía de identificación. */ + DescripGuiaIdentificacion?: string + /** Peso amparado por la guía de identificación. */ + PesoGuiaIdentificacion?: number + } + CartaPorteMercancia: { + /** Clave del bien o producto transportado (catCartaPorte:c_BienesTransp). */ + BienesTransp: string + /** Clave STCC para transporte ferroviario cuando corresponda. */ + ClaveSTCC?: string + /** Descripción comercial del bien transportado. */ + Descripcion: string + /** Cantidad total de unidades del bien. */ + Cantidad: number + /** Clave de unidad (c_ClaveUnidad) aplicable a la cantidad. */ + ClaveUnidad: string + /** Texto descriptivo de la unidad de medida. */ + Unidad?: string + /** Dimensiones físicas de la mercancía (largo x ancho x alto) si aplica. */ + Dimensiones?: string + /** Indicador de si la mercancía es material peligroso ("Sí" / "No"). */ + MaterialPeligroso?: string + /** Clave del material peligroso (c_MaterialPeligroso) cuando MaterialPeligroso es Sí. */ + CveMaterialPeligroso?: string + /** Clave del tipo de embalaje utilizado (c_TipoEmbalaje). */ + Embalaje?: string + /** Descripción adicional del embalaje. */ + DescripEmbalaje?: string + /** Sector regulado por COFEPRIS al que pertenece el producto. */ + SectorCOFEPRIS?: string + /** Nombre del ingrediente activo (productos regulados). */ + NombreIngredienteActivo?: string + /** Nombre químico del producto cuando aplica. */ + NomQuimico?: string + /** Denominación genérica del producto farmacéutico. */ + DenominacionGenericaProd?: string + /** Denominación distintiva (marca) del producto farmacéutico. */ + DenominacionDistintivaProd?: string + /** Nombre o razón social del fabricante. */ + Fabricante?: string + /** Fecha de caducidad del producto (AAAAMMDD o formato aplicable). */ + FechaCaducidad?: string + /** Número de lote del medicamento. */ + LoteMedicamento?: string + /** Forma farmacéutica (tableta, cápsula, solución, etc.). */ + FormaFarmaceutica?: string + /** Condiciones especiales de transporte (refrigeración, frágil, etc.). */ + CondicionesEspTransp?: string + /** Registro sanitario o folio de autorización. */ + RegistroSanitarioFolioAutorizacion?: string + /** Número de permiso de importación. */ + PermisoImportacion?: string + /** Folio VUCEM de importación. */ + FolioImpoVUCEM?: string + /** Número CAS para sustancias químicas. */ + NumCAS?: string + /** Razón social de la empresa importadora. */ + RazonSocialEmpImp?: string + /** Número de registro sanitario o plaguicida COFEPRIS. */ + NumRegSanPlagCOFEPRIS?: string + /** Información adicional del fabricante. */ + DatosFabricante?: string + /** Información del formulador del producto. */ + DatosFormulador?: string + /** Información del maquilador (si aplica). */ + DatosMaquilador?: string + /** Uso autorizado del producto. */ + UsoAutorizado?: string + /** Peso en kilogramos de la mercancía (puede ser peso neto o bruto según contexto). */ + PesoEnKg: number + /** Valor monetario de la mercancía. */ + ValorMercancia?: number + /** Clave de moneda (c_Moneda) del valor de la mercancía. */ + Moneda?: string + /** Fracción arancelaria aplicable (c_FraccionArancelaria). */ + FraccionArancelaria?: string + /** UUID asociado al complemento de Comercio Exterior relacionado. */ + UUIDComercioExt?: string + /** Tipo de materia prima (si aplica para minerales, sustancias, etc.). */ + TipoMateria?: string + /** Descripción de la materia prima. */ + DescripcionMateria?: string + /** Documentos aduaneros asociados a la mercancía. */ + DocumentacionAduanera?: components['schemas']['CartaPorteDocumentacionAduanera'][] + /** Guías de identificación asociadas. */ + GuiasIdentificacion?: components['schemas']['CartaPorteGuiaIdentificacion'][] + /** Detalle de cantidades transportadas por origen/destino. */ + CantidadTransporta?: components['schemas']['CartaPorteCantidadTransporta'][] + /** Detalle de pesos y piezas de la mercancía. */ + DetalleMercancia?: components['schemas']['CartaPorteDetalleMercancia'][] + } + CartaPorteIdentificacionVehicular: { + /** Configuración vehicular (catCartaPorte:c_ConfigAutotransporte) del vehículo primario. */ + ConfigVehicular: string + /** Peso bruto vehicular máximo permitido. */ + PesoBrutoVehicular: number + /** Placa del vehículo motor. */ + PlacaVM: string + /** Año modelo del vehículo motor. */ + AnioModeloVM: string + } + CartaPorteSeguros: { + /** Nombre de la aseguradora de responsabilidad civil. */ + AseguraRespCivil: string + /** Número de póliza de responsabilidad civil. */ + PolizaRespCivil: string + /** Aseguradora contra daños al medio ambiente. */ + AseguraMedAmbiente?: string + /** Número de póliza de medio ambiente. */ + PolizaMedAmbiente?: string + /** Aseguradora de la carga. */ + AseguraCarga?: string + /** Número de póliza de la carga. */ + PolizaCarga?: string + /** Prima total de los seguros contratados. */ + PrimaSeguro?: number + } + CartaPorteRemolque: { + /** Subtipo de remolque (catCartaPorte:c_SubTipoRem). */ + SubTipoRem?: string + /** Placa del remolque. */ + Placa?: string + } + CartaPorteAutotransporte: { + /** Clave del permiso SCT del autotransporte. */ + PermSCT: string + /** Número del permiso SCT. */ + NumPermisoSCT: string + /** Datos de identificación del vehículo principal. */ + IdentificacionVehicular: components['schemas']['CartaPorteIdentificacionVehicular'] + /** Información de seguros aplicables. */ + Seguros: components['schemas']['CartaPorteSeguros'] + /** Lista de remolques acoplados. */ + Remolques?: components['schemas']['CartaPorteRemolque'][] + } + CartaPorteContenedorMaritimo: { + /** Tipo de contenedor marítimo (ISO / catálogo SAT). */ + TipoContenedor?: string + /** Matrícula o número identificador del contenedor. */ + MatriculaContenedor?: string + /** Número de precinto o sello de seguridad. */ + NumPrecinto?: string + /** Identificador CCP relacionado cuando se reutiliza información. */ + IdCCPRelacionado?: string + /** Placa del vehículo motor asociado (si aplica en transbordo). */ + PlacaVMCCP?: string + /** Fecha de certificación CCP del contenedor. */ + FechaCertificacionCCP?: string + RemolquesCCP?: { + /** Subtipo de remolque relacionado (CCP). */ + SubTipoRemCCP?: string + /** Placa del remolque relacionado (CCP). */ + PlacaCCP?: string + }[] + } + CartaPorteTransporteMaritimo: { + /** Clave del permiso SCT de la embarcación. */ + PermSCT: string + /** Número de permiso SCT de la embarcación. */ + NumPermisoSCT: string + /** Nombre de la aseguradora marítima. */ + NombreAseg?: string + /** Número de póliza de seguro marítimo. */ + NumPolizaSeguro?: string + /** Tipo de embarcación (catCartaPorte:c_TipoEmbarcacion). */ + TipoEmbarcacion?: string + /** Matrícula de la embarcación. */ + Matricula?: string + /** Número OMI (IMO number) de la embarcación. */ + NumeroOMI?: string + /** Año de construcción de la embarcación. */ + AnioEmbarcacion?: string + /** Nombre propio de la embarcación. */ + NombreEmbarc?: string + /** Nacionalidad o bandera de la embarcación. */ + NacionalidadEmbarc?: string + /** Toneladas de arqueo bruto. */ + UnidadesDeArqBruto?: number + /** Tipo de carga (granel, contenedores, líquidos, etc.). */ + TipoCarga?: string + /** Longitud total de la embarcación (eslora). */ + Eslora?: number + /** Ancho máximo de la embarcación (manga). */ + Manga?: number + /** Calado máximo. */ + Calado?: number + /** Altura del puntal. */ + Puntal?: number + /** Nombre de la línea naviera. */ + LineaNaviera?: string + /** Nombre del agente naviero. */ + NombreAgenteNaviero?: string + /** Número de autorización del agente naviero. */ + NumAutorizacionNaviero?: string + /** Número de viaje o rotación. */ + NumViaje?: string + /** Número de conocimiento de embarque. */ + NumConocEmbarc?: string + /** Permiso temporal de navegación. */ + PermisoTempNavegacion?: string + /** Lista de contenedores asociados al embarque. */ + Contenedor?: components['schemas']['CartaPorteContenedorMaritimo'][] + } + CartaPorteTransporteAereo: { + /** Clave del permiso SCT para transporte aéreo. */ + PermSCT?: string + /** Número de permiso SCT. */ + NumPermisoSCT?: string + /** Matrícula de la aeronave. */ + MatriculaAeronave?: string + /** Nombre de la aseguradora aérea. */ + NombreAseg?: string + /** Número de póliza de seguro de la aeronave. */ + NumPolizaSeguro?: string + /** Número de guía aérea (Air Waybill). */ + NumeroGuia?: string + /** Lugar donde se celebró el contrato de transporte. */ + LugarContrato?: string + /** Código del transportista aéreo. */ + CodigoTransportista?: string + /** RFC del embarcador. */ + RFCEmbarcador?: string + /** Número de registro tributario extranjero del embarcador. */ + NumRegIdTribEmbarc?: string + /** País de residencia fiscal del embarcador. */ + ResidenciaFiscalEmbarc?: string + /** Nombre o razón social del embarcador. */ + NombreEmbarcador?: string + } + CartaPorteDerechosDePaso: { + /** Tipo de derecho de paso ferroviario. */ + TipoDerechoDePaso?: string + /** Kilometraje cubierto/pagado en el derecho de paso. */ + KilometrajePagado?: number + } + CartaPorteContenedorFerroviario: { + /** Tipo de contenedor ferroviario. */ + TipoContenedor?: string + /** Peso del contenedor vacío. */ + PesoContenedorVacio?: number + /** Peso neto de la mercancía contenida. */ + PesoNetoMercancia?: number + } + CartaPorteCarroFerroviario: { + /** Tipo de carro ferroviario. */ + TipoCarro?: string + /** Matrícula o número identificador del carro. */ + MatriculaCarro?: string + /** Número de guía asociado al carro. */ + GuiaCarro?: string + /** Toneladas netas transportadas en el carro. */ + ToneladasNetasCarro?: number + /** Contenedores asociados al carro. */ + Contenedor?: components['schemas']['CartaPorteContenedorFerroviario'][] + } + CartaPorteTransporteFerroviario: { + /** Tipo de servicio ferroviario (regular, intermodal, etc.). */ + TipoDeServicio?: string + /** Tipo de tráfico (nacional, internacional, etc.). */ + TipoDeTrafico?: string + /** Nombre de la aseguradora ferroviaria. */ + NombreAseg?: string + /** Número de póliza de seguro ferroviario. */ + NumPolizaSeguro?: string + /** Lista de derechos de paso aplicados. */ + DerechosDePaso?: components['schemas']['CartaPorteDerechosDePaso'][] + /** Lista de carros ferroviarios involucrados. */ + Carro?: components['schemas']['CartaPorteCarroFerroviario'][] + } + /** Domicilio relacionado a la ubicación en el complemento Carta Porte. */ + CartaPorteDomicilio: { + /** Calle del domicilio de origen y/o destino (requerida en XSD). */ + Calle?: string + /** Número exterior donde se ubica el domicilio. */ + NumeroExterior?: string + /** Número interior del domicilio, si existe. */ + NumeroInterior?: string + /** Colonia o dato análogo del domicilio. */ + Colonia?: string + /** Ciudad, población o distrito del domicilio. */ + Localidad?: string + /** Referencia geográfica adicional (ej. coordenadas GPS). */ + Referencia?: string + /** Municipio, delegación, alcaldía o análogo del domicilio. */ + Municipio?: string + /** Clave de estado, entidad o región (ISO 3166-2 conforme catálogo SAT). */ + Estado: string + /** Clave del país (catálogo c_Pais, ISO 3166-1). */ + Pais: string + /** Código postal del domicilio. */ + CodigoPostal: string + } + CartaPorteMercancias: { + /** Suma del peso bruto total de las mercancías (aéreo y ferroviario). */ + PesoBrutoTotal: number + /** Clave de unidad de medida estandarizada del peso (catCartaPorte:c_ClaveUnidadPeso). */ + UnidadPeso: string + /** Suma de los valores PesoNeto de cada DetalleMercancia. */ + PesoNetoTotal?: number + /** Número total de mercancías (cantidad de nodos Mercancia). */ + NumTotalMercancias: number + /** Importe pagado por la tasación de las mercancías (vía aérea). */ + CargoPorTasacion?: number + /** Indica si aplica logística inversa, recolección o devolución. */ + LogisticaInversaRecoleccionDevolucion?: string + /** Arreglo requerido con las mercancías transportadas. */ + Mercancia: components['schemas']['CartaPorteMercancia'][] + /** Datos del autotransporte de carga federal. */ + Autotransporte?: components['schemas']['CartaPorteAutotransporte'] + /** Datos de la embarcación para transporte marítimo. */ + TransporteMaritimo?: components['schemas']['CartaPorteTransporteMaritimo'] + /** Datos del transporte aéreo utilizado. */ + TransporteAereo?: components['schemas']['CartaPorteTransporteAereo'] + /** Datos del transporte ferroviario utilizado. */ + TransporteFerroviario?: components['schemas']['CartaPorteTransporteFerroviario'] + } + NamespaceRequiredProperties: Record + /** Namespace */ + NamespaceProperties: { + /** Prefijo o nombre del namespace. */ + prefix?: string + /** + * Format: url + * Dirección URL asociada al namespace. + */ + uri?: string + /** + * Format: url + * Dirección URL del esquema de validación XSD. + */ + schema_location?: string + } + CommonAddressProperties: { + /** Nombre de la calle */ + street?: string + /** Número exterior. */ + exterior?: string + /** Número interior. */ + interior?: string + /** Colonia */ + neighborhood?: string + /** Ciudad */ + city?: string + /** Municipio o delegación */ + municipality?: string + /** Código postal */ + zip?: string + } + /** Objeto Webhook */ + Webhook: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['WebhookProperties'] + WebhookSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Webhook'][] + } + WebhookProperties: { + /** Id de la organización la cual se está dando de alta el webhook. */ + organization?: string + /** Ambiente en el cual se está dando de alta el webhook. */ + livemode?: boolean + /** Eventos a los que está suscrito el webhook. El valor "*" puede aparecer en respuestas existentes, pero no se acepta al crear o actualizar un webhook; envía los nombres de eventos explícitos. */ + enabled_events?: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + | '*' + )[] + /** + * Format: uri + * Http ruta para el webhook + */ + url?: string + /** + * Status del webhook + * @enum {string} + */ + status?: 'enabled' | 'disabled' + description?: string + } + /** Webhook */ + WebhookCreateInput: { + /** + * Format: uri + * URL del webhook a dar de alta para recibir notificaciones. + */ + url: string + /** Los eventos a los que el webhook se suscribirá. */ + enabled_events: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + )[] + } + /** Webhook */ + WebhookCreateEdit: { + /** + * Estatus del webhook + * @enum {string} + */ + status: 'disabled' | 'enabled' + /** Los eventos a los que el webhook se suscribirá. */ + enabled_events: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + )[] + } + /** Objeto Customer */ + Customer: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['CustomerNonEditableProperties'] & + components['schemas']['CustomerProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + curp?: string + external_id?: string + } + CustomerSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Customer'][] + } + CustomerNonEditableProperties: { + /** + * Enlace a una página alojada donde el cliente puede editar su información una vez. + * Ejemplo: https://auto.facturapi.io/tax-info/abcdWXYZ1234 + */ + edit_link?: string | null + /** + * Format: date-time + * Fecha de expiración del enlace de edición. + */ + edit_link_expires_at?: Date | string | null + /** + * Format: date-time + * Fecha en la que la información fiscal fue validado por el SAT. + */ + sat_validated_at?: Date | string | null + } + CustomerProperties: components['schemas']['CustomerCommonProperties'] & { + address?: components['schemas']['CommonAddressProperties'] & { + /** Si el país es México ("MEX"), contiene el nombre del Estado o Entidad Federativa. Para extranjeros contiene el código de Estado de acuerdo al estándar [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2), que puedes consultar en nuestro [Catálogo de Estados](https://dashboard.facturapi.io/catalogs/state). */ + state?: string + /** + * Código de país acorde al estándar [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3), del [Catálogo de Países](https://dashboard.facturapi.io/catalogs/country). + * @default MEX + */ + country?: string + } + } + CustomerCommonProperties: { + /** Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id?: string | null + /** Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). */ + tax_system?: string | null + /** + * Format: email + * Dirección de correo electrónico al cual enviar las facturas generadas. + */ + email?: string + /** Teléfono del cliente. */ + phone?: string | null + /** Uso de CFDI por defecto. */ + default_invoice_use?: string + } + /** Omite los parámetros para eliminar un borrador. Los documentos emitidos requieren motivo; los motivos 01 y 04 también requieren substitution. */ + CancellationQueryInput: + | { + /** @enum {string} */ + motive: '01' | '04' + /** ID de Facturapi o UUID del documento sustituto. */ + substitution: string + } + | { + /** @enum {string} */ + motive: '02' | '03' + substitution?: string + } + | { + motive?: never + substitution?: never + } + /** + * Customer with edit link + * La información del cliente puede estar incompleta cuando createEditLink=true. Los campos enviados deben conservar formatos válidos. + */ + CustomerCreateWithEditLinkInput: components['schemas']['CustomerProperties'] & { + /** Si se envía, debe ser un régimen fiscal válido. Omitirlo permite guardar información fiscal incompleta. */ + tax_system?: string + } + CustomerCreateCommonInput: { + /** Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name: string + /** + * Format: email + * Dirección de correo electrónico al cual enviar las facturas generadas. + */ + email?: string + /** Teléfono del cliente. */ + phone?: string | null + /** Uso de CFDI por defecto. */ + default_invoice_use?: string + } + CustomerNationalAddressInput: WithRequired< + components['schemas']['CommonAddressProperties'], + 'zip' + > & { + state?: string + /** + * @default MEX + * @constant + */ + country?: 'MEX' + } + CustomerForeignAddressInput: components['schemas']['CommonAddressProperties'] & { + /** Código ISO 3166-1 alpha-3 distinto de MEX. Es necesario para aplicar las reglas de cliente extranjero. */ + country: string + state?: string + } + /** + * Cliente nacional + * País MEX, u omitido. Requiere razón social, RFC, régimen fiscal y código postal. Los RFC genéricos usan CustomerGenericCreateInput. + */ + CustomerNationalCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id: string + /** Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). */ + tax_system: string + address: components['schemas']['CustomerNationalAddressInput'] + } + /** + * Cliente extranjero + * Requiere razón social y domicilio con un país explícito distinto de MEX. El identificador fiscal y el código postal son opcionales; el régimen fiscal predeterminado es 616. + */ + CustomerForeignCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id?: string | null + /** + * Los clientes extranjeros usan 616. Omitirlo, enviar null o una cadena vacía usa el valor predeterminado. + * @default 616 + * @enum {string|null} + */ + tax_system?: '616' | null | '' + address: components['schemas']['CustomerForeignAddressInput'] + } + /** + * RFC genérico + * RFC de público en general XAXX010101000 o RFC genérico extranjero XEXX010101000. Requiere razón social y RFC. El régimen fiscal predeterminado es 616. Si se envía domicilio mexicano, requiere código postal. + */ + CustomerGenericCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** @enum {string} */ + tax_id: 'XAXX010101000' | 'XEXX010101000' + /** + * @default 616 + * @enum {string} + */ + tax_system?: '616' + address?: + | components['schemas']['CustomerNationalAddressInput'] + | components['schemas']['CustomerForeignAddressInput'] + } + /** + * Customer + * Los campos requeridos dependen del país y del RFC. Omitir el país equivale a México. Con createEditLink=true se usa CustomerCreateWithEditLinkInput. + */ + CustomerCreateInput: + | components['schemas']['CustomerNationalCreateInput'] + | components['schemas']['CustomerForeignCreateInput'] + | components['schemas']['CustomerGenericCreateInput'] + /** Product */ + LineItemProductInput: components['schemas']['ProductProperties'] + /** Product */ + LineItemProductEgresoInput: components['schemas']['ProductEgresoProperties'] + /** Product */ + LineItemTrasladoProductInput: { + /** Descripción del bien o servicio como aparecerá en la factura. */ + description: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). */ + product_key?: string + /** + * Clave de unidad de medida, del catálogo del SAT. El valor por default `"H87"` (elemento) es la clave para representar una pieza o unidad de venta (lápiz, cuaderno, televisión, etc). + * Si la unidad de tu producto es kilogramos, litros, horas u otra unidad, te proporcionamos una manera conveniente de encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default H87 + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Elemento + */ + unit_name?: string + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + } + LineItemProduct: { + /** ID del producto base. Sólo presente si se utilizó como base un objeto `Product` guardado previamente. */ + id?: string + } & components['schemas']['ProductProperties'] + Parts: { + /** Descripción del producto o servicio. */ + description?: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra herramienta de búsqueda de claves. */ + product_key?: string + /** Cantidad */ + quantity?: number + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + /** Precio unitario */ + unit_price?: number + /** Nombre de la unidad de medida que expresa la cantidad. */ + unit_name?: string + /** Números de pedimento aduanal asociados a esta parte. */ + customs_keys?: string[] + } + PartInput: WithRequired< + components['schemas']['Parts'], + 'description' | 'product_key' + > + /** Objeto Product */ + Product: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['ProductProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization: string + } + ProductSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Product'][] + } + ProductProperties: WithRequired< + components['schemas']['ProductEditableProperties'], + 'description' | 'product_key' | 'price' + > + ProductEditableProperties: { + /** Descripción del bien o servicio como aparecerá en la factura. */ + description?: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). */ + product_key?: string + /** Precio por unidad del bien o servicio. Este valor representará el precio con IVA incluido o sin él, dependiendo del valor de `tax_included`. */ + price?: number + /** + * - `true`: Indica que todos los impuestos aplicables están incluidos en el precio (atributo price) y se desglosarán automáticamente al emitir la factura. + * - `false`: Indica que el atributo price no incluye impuestos, por lo que aquellos impuestos a aplicar se sumarán en el precio final. + * @default true + */ + tax_included?: boolean + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * - `06`: Sí objeto de impuesto, no IVA trasladado. + * - `07`: No traslado de IVA, pero desglose de IEPS. + * - `08`: No traslado de IVA sin desglose de IEPS. + * @default 02 + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** + * Lista de impuestos que deberán aplicarse a este producto. + * + * Resolución cuando `taxes` se omite o es `null`: + * - `taxability` omitido o `"02"`: se agrega IVA trasladado 16%. + * - `taxability` en `"01"`, `"03"`, `"04"`, `"05"`, `"06"` o `"08"`: se guarda `[]`. + * - `taxability = "07"`: la solicitud es inválida; debes enviar al menos un IEPS de traslado y no incluir IVA. + * + * Si envías `taxes` explícitamente, se usa el arreglo enviado. + * @default [ + * { + * "type": "IVA", + * "rate": 0.16 + * } + * ] + */ + taxes?: components['schemas']['BaseTax'][] + /** + * Arreglo de impuestos locales (estatales o municipales), en caso de haberlos. + * @default [] + */ + local_taxes?: components['schemas']['LocalTax'][] + /** + * Clave de unidad de medida, del catálogo del SAT. El valor por default `"H87"` (elemento) es la clave para representar una pieza o unidad de venta (lápiz, cuaderno, televisión, etc). + * Si la unidad de tu producto es kilogramos, litros, horas u otra unidad, puedes encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default H87 + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Elemento + */ + unit_name?: string + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + } + ProductEgresoProperties: { + /** Resumen de la operación en una sola descripción. Deben mencionarse cada uno de los productos que contempla el descuento, devolución o bonificación aplicada y que contienen las facturas relacionadas. Si el egreso está basado en un pocentaje (como al aplicar un 30% de descuento), dicho porcentaje debe incluirse en la descripción junto al nombre del producto que corresponda. */ + description: string + /** + * Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). + * @default 84111506 + */ + product_key?: string + /** Suma total de la cantidad devuelta, descontada o bonificada. */ + price: number + /** + * - `true`: Indica que todos los impuestos aplicables están incluidos en el precio (atributo price) y se desglosarán automáticamente al emitir la factura. + * - `false`: Indica que el atributo price no incluye impuestos, por lo que aquellos impuestos a aplicar se sumarán en el precio final. + * @default true + */ + tax_included?: boolean + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * @default 02 + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** + * Lista de impuestos que deberán aplicarse a este producto. + * + * Resolución cuando `taxes` se omite o es `null`: + * - `taxability` omitido o `"02"`: se agrega IVA trasladado 16%. + * - `taxability` en `"01"`, `"03"`, `"04"`, `"05"`, `"06"` o `"08"`: se guarda `[]`. + * - `taxability = "07"`: la solicitud es inválida; debes enviar al menos un IEPS de traslado y no incluir IVA. + * + * Si envías `taxes` explícitamente, se usa el arreglo enviado. + * @default [ + * { + * "type": "IVA", + * "rate": 0.16 + * } + * ] + */ + taxes?: components['schemas']['BaseTax'][] + /** + * Arreglo de impuestos locales (estatales o municipales), en caso de haberlos. + * @default [] + */ + local_taxes?: components['schemas']['LocalTax'][] + /** + * Clave de unidad de medida, del catálogo del SAT. + * Puedes encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default ACT + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Actividad + */ + unit_name?: string + } + /** Payment */ + PaymentInput: { + /** Código de la forma de pago según el [catálogo del SAT](#forma-de-pago). También puedes utilizar la constante `PaymentForm` incluida en nuestras librerías. */ + payment_form: string + /** Arreglo que incluye un elemento por cada comprobante de ingreso relacionado a este pago. Lo más común es que el pago esté relacionado a un sólo comprobante de ingreso. Un caso en el que se agrega más de un elemento es cuando se recibe (por ejemplo) un sólo depósito que ampara el pago de 2 facturas relacionadas. En lugar de expedir un comprobante de recepción de pago por cada factura, debes expedir sólo uno relacionando los 2 comprobantes. */ + related_documents: { + /** + * Format: uuid + * Folio fiscal ó UUID del comprobante de ingreso relacionado. + */ + uuid: string + /** + * Cantidad del pago correspondiente al comprobante relacionado, + * usando el método de pago indicado en este elemento del arreglo + * de pagos. Este valor debe ser expresado en la moneda definida + * en `related_documents[].currency`. + */ + amount: number + /** Arreglo con impuestos del documento relacionado que aplican al pago realizado. */ + taxes: { + /** Base utilizada para el cálculo del impuestos. */ + base: number + /** + * Tipo de impuesto. + * @enum {string} + */ + type: 'IVA' | 'ISR' | 'IEPS' + /** Tasa o cuota del impuesto */ + rate: number + /** + * Tipo factor. + * @default Tasa + * @enum {string} + */ + factor?: 'Tasa' | 'Cuota' | 'Exento' + /** + * Indica si el impuesto es una retención (`true`) o un traslado (`false`). + * @default false + */ + withholding?: boolean + }[] + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * - `06`: Sí objeto de impuesto, no IVA trasladado. + * - `07`: No traslado de IVA, pero desglose de IEPS. + * - `08`: No traslado de IVA sin desglose de IEPS. + * + * Si se omite, se utiliza `01` cuando `taxes` está vacío y `02` cuando contiene al menos un impuesto. + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** Número de parcialidad del pago. */ + installment: number + /** Cantidad que estaba pendiente por pagar antes de recibir este pago. Este valor se expresa en la moneda definida en `related_documents[].currency`. */ + last_balance: number + /** + * Si la moneda utilizada en la factura relacionada no es moneda nacional (MXN), debe especificarse su valor acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** Obligatorio cuando la moneda del documento relacionado es distinta a la moneda de pago. Tipo de cambio entre las dos monedas al momento del pago. Ejemplo: La factura de ingreso relacionada se registra en USD, mientras que el pago actual se realiza en MXN, este atributo debería registrarse como `0.45` (USD/MXN). */ + exchange?: number + /** Opcionalmente se puede incluir el número de folio del documento relacionado. */ + folio_number?: number + /** Opcionalmente se puede incluir la serie del documento relacionado. */ + series?: string | null + }[] + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Format: date-time + * Fecha en que se recibió el pago. Si se omite, se utiliza la fecha y hora actuales. Inclúyela cuando el pago sea anterior a la emisión del comprobante. No se permiten fechas futuras. + */ + date?: Date | string + /** Número de cheque, de autorización, de referencia, clave de rastreo SPEI, línea de captura o algún número de referencia que permita identificar la operación correspondiente al pago efectuado. */ + numOperacion?: string + /** RFC de la entidad emisora de la cuenta de origen, es decir, la operadora, banco, institución financiera, emisor de monedero electrónico, etc. */ + rfcEmisorCtaOrd?: string + /** Nombre del banco ordenante. */ + nomBancoOrdExt?: string + /** Número de cuenta con la que se realizó el pago. */ + ctaOrdenante?: string + /** RFC de la entidad de la cuenta operadora destino, es decir, la operadora, banco, institución financiera, emisor de monedero electrónico, etc. */ + rfcEmisorCtaBen?: string + /** Número de cuenta donde se recibió el pago. */ + ctaBeneficiario?: string + /** + * Clave del tipo de cadena de pago que genera la entidad receptora del pago. + * Si existe este campo, es obligatorio registrar los campos `certPago`, `cadPago` y `selloPago`. + * @enum {string} + */ + tipoCadPago?: '01' + /** + * Format: base64 + * Certificado que corresponde al pago, como una cadena de texto en formato base 64. + */ + certPago?: string + /** Cadena original del comprobante de pago generado por la entidad emisora de la cuenta beneficiaria. */ + cadPago?: string + /** + * Format: base64 + * Sello digital que se asocie al pago expresado como una cadena de texto en formato base 64. + */ + selloPago?: string + } + /** Objeto con información parcial del cliente receptor del comprobante. Para obtener el objeto `Customer` completo, deberás consultarlo con el método de [Obtener Cliente]('#/operation/getCustomer'). */ + CustomerInfo: { + /** ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado */ + id?: string + /** Nombre Fiscal o Razón Social del cliente, *sin* incluir el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** RFC del cliente. */ + tax_id?: string + address?: { + /** + * Format: ISO 3166-1 alpha-3 + * Código de País acorde al estándar ISO 3166-1 alpha-3, del Catálogo de Países. + */ + country?: string + zip?: string + } + tax_system?: string | null + } + /** Objeto con información parcial del cliente receptor del comprobante. Para obtener el objeto `Customer` completo, deberás consultarlo con el método de [Obtener Cliente]('#/operation/getCustomer'). */ + CustomerComercioExterior: { + /** ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado */ + id?: string + } + RelatedDocumentInput: WithRequired< + components['schemas']['RelatedDocument'], + 'relationship' + > + RelatedDocument: { + /** Clave de relación del catálogo del SAT que puedes consultar en [esta tabla](#relacion-entre-facturas). Es requerido cuando se envíe el parámetro `related_documents`. */ + relationship?: string + /** + * Folios fiscales (UUID) de facturas relacionadas. + * @default [] + */ + documents?: string[] + } + /** + * Status de generación del ZIP: + * - `created`: la solicitud fue creada y programada. + * - `processing`: la generación está en curso. + * - `finished`: el ZIP está listo para descargarse. + * - `failed`: falló la programación o generación. + * - `none`: valor legado; normalmente no se regresa en este flujo. + * @enum {string} + */ + InvoiceZipRequestStatus: + 'created' | 'processing' | 'finished' | 'failed' | 'none' + /** + * Tipo de factura (`I` Ingreso, `E` Egreso, `T` Traslado, `N` Nómina o `P` Pago). + * @enum {string} + */ + InvoiceZipRequestInvoiceType: 'I' | 'E' | 'T' | 'N' | 'P' + InvoiceZipRequestCreateInput: { + year: number + month: number + /** @default issuing */ + issuer_type?: components['schemas']['IssuingType'] + /** Tipos de factura a incluir. Por defecto se incluyen todos. */ + invoice_types?: components['schemas']['InvoiceZipRequestInvoiceType'][] + } + /** Objeto InvoiceZipRequest */ + InvoiceZipRequest: components['schemas']['ResourceAutoGeneratedProps'] & { + /** + * Siempre es `true` para este flujo. + * @constant + */ + livemode?: true + /** Identificador de la organización. */ + organization: string + issuer_type: components['schemas']['IssuingType'] + /** Tipos normalizados de las facturas incluidas. */ + invoice_types: components['schemas']['InvoiceZipRequestInvoiceType'][] + /** + * Format: date-time + * Inicio inclusivo del mes solicitado. + */ + start_date: Date | string + /** + * Format: date-time + * Fin inclusivo del mes solicitado. + */ + end_date: Date | string + status: components['schemas']['InvoiceZipRequestStatus'] + /** Número total de facturas por procesar. */ + document_count: number + /** Número de facturas procesadas. */ + processed_document: number + /** Facturas que no pudieron agregarse al ZIP. */ + failed_documents: string[] + /** + * Format: date-time + * Fecha en que se programó el procesamiento. + */ + scheduled_at?: Date | string + /** + * Format: date-time + * Momento en que comenzó el procesamiento, si existe. + */ + processing_started_at?: Date | string + } + InvoiceZipRequestSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['InvoiceZipRequest'][] + } + /** Objeto Invoice */ + Invoice: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['InvoiceProperties'] + /** Objeto Invoice con status draft */ + InvoiceDraft: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['InvoiceDraftProperties'] + InvoiceSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Invoice'][] + } + InvoiceRequiredProperties: Record + InvoiceProperties: { + /** + * Estado actual de la factura. `failed` indica que el timbrado en segundo plano o la recuperación automática del CFDI terminó sin éxito. + * @enum {string} + */ + status?: 'pending' | 'valid' | 'canceled' | 'draft' | 'failed' + /** + * Estado actual de la solicitud de cancelación, en caso de haberla realizado. Puedes leer más a detalle en la sección de [Cancelar Factura](#tag/invoice/operation/deleteInvoice)). + * @enum {string} + */ + cancellation_status?: + 'none' | 'pending' | 'accepted' | 'rejected' | 'expired' | 'verifying' + /** + * Format: date-time + * Fecha en la que se canceló el CFDI con hora aproximada. + */ + canceled_at?: Date | string | null + /** + * Format: uri + * Dirección URL para verificar el estado del CFDI en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la factura. + */ + verification_url?: string + /** + * Format: date-time + * Fecha de expedición en formato ISO8601. Puede ser null en borradores. + */ + date: Date | string | null + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + * @enum {string} + */ + type?: 'I' | 'E' | 'P' | 'N' | 'T' + customer?: components['schemas']['CustomerInfo'] | null + /** Monto total facturado. */ + total?: number + /** + * Format: uuid + * Folio fiscal de la factura, asignado por el SAT. + */ + uuid?: string + /** Número de folio autoincremental para control interno y sin validez fiscal. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. En el PDF se imprime junto al número de folio. */ + series?: string + /** Identificador que puedes usar para relacionar esta factura con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Total del complemento de Pago cuando la factura es tipo P. */ + total_payment_amount?: number + /** Total del monto pagado convertido de la moneda de pago a Pesos Mexicanos. */ + total_payment_amount_converted?: number + /** + * Este campo es asignado automáticamente por Facturapi. Indica si una factura + * con status `draft` está completa y lista para intentar timbrarse. Si el valor es `true`, puedes + * intentar timbrar la factura con el método [Timbrar Factura]('#/operation/stampInvoice'). + * Si el valor es `false`, debes usar el método [Actualizar Factura]('#/operation/updateDraftInvoice') + * para completar los campos faltantes. + * + * En una factura con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + /** Conceptos incluidos en el comprobante */ + items?: components['schemas']['LineItem'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocument'][] + /** + * En facturas con tipo I (Ingreso) y método de pago PPD, este campo lista los + * IDs de los comprobantes de pago cuyo arreglo de documentos relacionados incluye el UUID + * de esta factura. Este campo es llenado por Facturapi en el momento en que se crea o importa + * el comprobante de pago (tipo P), siempre y cuando pertenezca a la misma organización. + * @default [] + */ + received_payment_ids?: string[] + /** + * En facturas con tipo P (Pago), este arreglo lista los IDs de los comprobantes de ingreso + * listados en el arreglo de documentos relacionados. Este campo es llenado por Facturapi siempre + * y cuando el comprobante relacionado también esté registrado en Facturapi y pertenezca a la misma organización. + * @default [] + */ + target_invoice_ids?: string[] + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en la factura. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementProperties'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + stamp?: components['schemas']['Stamp'] | null + /** ID de la organización a la que pertenece este recurso. */ + organization?: string | null + issuer_type?: components['schemas']['IssuingType'] + cfdi_version?: number + issuer_info?: components['schemas']['CustomerInfo'] + /** @enum {string} */ + payment_method?: 'PUE' | 'PPD' + use?: string + amount_due?: number + /** Format: uri */ + verification_carta_porte?: string + conditions?: string + export?: string + global?: { + /** @enum {string} */ + periodicity: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + months: string + year: number + } + } + InvoiceDraftProperties: { + /** + * Estado actual de la factura. + * @enum {string} + */ + status?: 'pending' | 'valid' | 'canceled' | 'draft' + /** + * Estado actual de la solicitud de cancelación, en caso de haberla realizado. Puedes leer más a detalle en la sección de [Cancelar Factura](#tag/invoice/operation/deleteInvoice)). + * @enum {string} + */ + cancellation_status?: + 'none' | 'pending' | 'accepted' | 'rejected' | 'expired' | 'verifying' + /** + * Format: uri + * Dirección URL para verificar el estado del CFDI en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la factura. + */ + verification_url?: string + /** + * Format: date-time + * Fecha de timbrado del comprobante en formato ISO8601 (UTC String). Si el estado es `draft`, este campo es nulo. + */ + date?: Date | string | null + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + * @enum {string} + */ + type?: 'I' | 'E' | 'P' | 'N' | 'T' + /** Cliente de la factura. Es null cuando el borrador no tiene cliente. */ + customer?: components['schemas']['CustomerInfo'] | null + /** Monto total facturado. */ + total?: number + /** + * Format: uuid + * Folio fiscal asignado por el SAT. En un borrador sin timbrar, este campo es null o se omite. + */ + uuid?: string | null + /** Número de folio autoincremental para control interno y sin validez fiscal. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. En el PDF se imprime junto al número de folio. */ + series?: string + /** Identificador que puedes usar para relacionar esta factura con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Conceptos incluidos en el comprobante */ + items?: components['schemas']['LineItem'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocument'][] + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en la factura. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementProperties'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + /** + * Este campo es asignado automáticamente por Facturapi. Indica si una factura + * con status `draft` está completa y lista para intentar timbrarse. Si el valor es `true`, puedes + * intentar timbrar la factura con el método [Timbrar Factura]('#/operation/stampInvoice'). + * Si el valor es `false`, debes usar el método [Actualizar Factura]('#/operation/updateDraftInvoice') + * para completar los campos faltantes. + * + * En una factura con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + stamp?: components['schemas']['Stamp'] | null + } + InvoiceableCommonInput: { + /** Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** + * Format: xml + * En caso de que necesites incluir más información en el PDF, este campo te permite enviar código HTML con tu propio contenido. + * + * Por seguridad, el código que puedes enviar está limitado a las siguientes etiquetas: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `div`, `p`, `span`, `small`, `br`, `b`, `i`, `ul`, `ol`, `li`, `strong`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th` y `td`. No se permiten atributos ni estilos. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** + * Si incluiste el parámetro `complements`, este campo es opcional; en cambio si incluiste el parámetro `addenda`, debes enviar la información necesaria para incluir estos namespaces en el documento XML. + * @default [] + */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia del cliente para la factura en curso. Utiliza este campo para peticiones de generación de facturas en las cuales necesites utilizar una configuración distinta al campo pdf_extra de la organización. */ + pdf_options?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostrarán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + InvoiceableCommonEditInput: { + /** Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** + * Format: xml + * En caso de que necesites incluir más información en el PDF, este campo te permite enviar código HTML con tu propio contenido. + * + * Por seguridad, el código que puedes enviar está limitado a las siguientes etiquetas: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `div`, `p`, `span`, `small`, `br`, `b`, `i`, `ul`, `ol`, `li`, `strong`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th` y `td`. No se permiten atributos ni estilos. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Si incluiste el parámetro `complements`, este campo es opcional; en cambio si incluiste el parámetro `addenda`, debes enviar la información necesaria para incluir estos namespaces en el documento XML. */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia del cliente para la factura en curso. Utiliza este campo para peticiones de generación de facturas en las cuales necesites utilizar una configuración distinta al campo pdf_extra de la organización. */ + pdf_options?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + /** Cliente receptor de la factura. */ + InvoiceCustomerInput: components['schemas']['CustomerCreateInput'] | string + InvoiceCommonInputProperties: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Estado inicial de la factura. Si se envía `draft`, la factura se guardará como borrador y no se timbrará ni se + * enviará al SAT. También al enviar `draft`, todos los campos requeridos se vuelven + * opcionales. Si se omite, el estado por default es `pending` y una vez timbrada (en la respuesta) este + * campo se actualizará a `valid`. Para facturas asíncronas, este campo se quedará en `pending` hasta que + * se timbre la factura. + * @default pending + * @enum {string} + */ + status?: 'pending' | 'draft' + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601. Si se omite, se utiliza la fecha y hora actuales. No puede ser anterior a 72 horas en el pasado ni posterior al presente. + */ + date?: Date | string + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** Identificador opcional que puedes usar para relacionar esta factura con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } & components['schemas']['InvoiceableCommonInput'] + InvoiceCommonEditInputProperties: { + /** + * Estado de la factura. El valor `draft` identifica un borrador que no se ha timbrado ni enviado al SAT. + * Sólo es posible editar facturas con este estado; al editarlas, no se puede cambiar `status`. + * @enum {string} + */ + status?: 'draft' + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). No puede ser anterior a 72 horas en el pasado, ni posterior al presente. + */ + date?: Date | string + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** Identificador opcional que puedes usar para relacionar esta factura con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } & components['schemas']['InvoiceableCommonEditInput'] + InvoiceDraftInputProperties: components['schemas']['InvoiceCommonEditInputProperties'] & { + /** Cliente receptor de la factura. */ + customer?: null | components['schemas']['CustomerCreateInput'] | string + } + /** Datos de la factura según su tipo y estado inicial. Omite status para timbrar; usa draft para guardar un borrador. */ + InvoiceCreateInput: + | ( + | (components['schemas']['InvoiceIngresoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceIngresoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceEgresoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceEgresoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoicePagoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoicePagoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceNominaInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceNominaEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceTrasladoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceTrasladoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + /** Ingreso */ + InvoiceIngresoInput: { + /** + * Tipo de comprobante. El valor default es `“I”` (Ingreso). + * @default I + * @enum {string} + */ + type?: 'I' + /** + * Conceptos a incluir en la factura. + * + * El número máximo de elementos que puedes incluir en una factura es de 5,000. Si necesitas + * emitir una factura con más de 5,000 conceptos, puedes dividir la transacción en varias facturas. + */ + items: components['schemas']['LineItemInput'][] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form: string + /** + * Código del método de pago según el catálogo del SAT. + * + * - `PUE`: Pago en Una sola Exhibición + * - `PPD`: Pago en Parcialidades o Diferido + * @default PUE + * @enum {string} + */ + payment_method?: 'PUE' | 'PPD' + /** + * Si se omite o es null, se utiliza el uso configurado en el cliente; si no tiene uno, se utiliza G03. Para clientes extranjeros o público en general se utiliza S01. + * + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos + * en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en + * nuestras librerías. + * + * Para factura global debe ingresarse la clave `S01`. + */ + use?: string | null + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos + * mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** Condiciones de pago */ + conditions?: string + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** Objeto requerido al crear una factura global. */ + global?: { + /** + * Periodicidad que abarca la factura global. + * + * - `day`: Diario + * - `week`: Semanal + * - `fortnight`: Quincenal + * - `month`: Mensual + * - `two_months`: Bimestral + * @enum {string} + */ + periodicity: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + */ + months: string + /** Año de la factura. */ + year: number + } + /** + * Indica si el comprobante ampara una operación de exportación. + * + * - `01`: No aplica + * - `02`: Definitiva con clave A1 + * - `03`: Temporal + * - `04`: Definitiva con clave distinta a A1 o cuando no existe enajenación en términos del CFF + * @default 01 + * @enum {string} + */ + export?: '01' | '02' | '03' | '04' + /** + * Complementos a incluir en la factura. Puedes incluir cualquier complemento en la + * factura si tú mismo construyes el nodo XML del complemento y usas el tipo `custom`. + * Es necesario agregar la información del complemento al PDF por separado usando el + * parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Egreso */ + InvoiceEgresoInput: { + /** @enum {string} */ + type: 'E' + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form: string + /** + * Código del método de pago según el catálogo del SAT. Para facturas de Egreso, + * este campo es opcional y el único valor permitido es `PUE` (Pago en Una sola Exhibición). + * @default PUE + * @enum {string} + */ + payment_method?: 'PUE' + /** + * Documentos relacionados con la nota de crédito. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** + * Conceptos a incluir en la nota de crédito. + * + * El número máximo de elementos que puedes incluir en el comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items: components['schemas']['LineItemEgresoInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default G02 + */ + use?: string + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier + * complemento en el comprobante si tú mismo construyes el nodo XML del + * complemento y usas el tipo `custom`. Es necesario agregar la información + * del complemento al PDF por separado usando el parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Pago */ + InvoicePagoInput: { + /** @enum {string} */ + type: 'P' + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Complementos a incluir en la factura. */ + complements: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Nómina */ + InvoiceNominaInput: { + /** @enum {string} */ + type: 'N' + /** Complementos a incluir en la factura. */ + complements: components['schemas']['InvoiceComplementInput'][] + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Traslado */ + InvoiceTrasladoInput: { + /** @enum {string} */ + type: 'T' + /** + * Conceptos a incluir en el comprobante de Traslado. + * + * El número máximo de elementos que puedes incluir en un comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items: components['schemas']['LineItemTrasladoInput'][] + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier complemento en + * el comprobante si tú mismo construyes el nodo XML del complemento y usas el tipo + * `custom`. Es necesario agregar la información del complemento al PDF por separado + * usando el parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en + * [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default S01 + */ + use?: string + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default XXX + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos + * (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Documentos relacionados con el comprobante. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Ingreso */ + InvoiceIngresoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'I' + /** + * Conceptos a incluir en la factura. + * + * El número máximo de elementos que puedes incluir en una factura es de 5,000. Si necesitas + * emitir una factura con más de 5,000 conceptos, puedes dividir la transacción en varias facturas. + */ + items?: components['schemas']['LineItemInput'][] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string | null + /** + * Código del método de pago según el catálogo del SAT. + * + * - `PUE`: Pago en Una sola Exhibición + * - `PPD`: Pago en Parcialidades o Diferido + * @enum {string} + */ + payment_method?: 'PUE' | 'PPD' + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos + * en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en + * nuestras librerías. + * + * Para factura global debe ingresarse la clave `S01`. + */ + use?: string | null + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos + * mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + */ + exchange?: number + /** Condiciones de pago */ + conditions?: string + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** Objeto requerido al crear una factura global. */ + global?: { + /** + * Periodicidad que abarca la factura global. + * + * - `day`: Diario + * - `week`: Semanal + * - `fortnight`: Quincenal + * - `month`: Mensual + * - `two_months`: Bimestral + * @enum {string} + */ + periodicity: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + */ + months: string + /** Año de la factura. */ + year: number + } + /** + * Indica si el comprobante ampara una operación de exportación. + * + * - `01`: No aplica + * - `02`: Definitiva con clave A1 + * - `03`: Temporal + * - `04`: Definitiva con clave distinta a A1 o cuando no existe enajenación en términos del CFF + * @enum {string} + */ + export?: '01' | '02' | '03' | '04' + /** + * Complementos a incluir en la factura. Puedes incluir cualquier complemento en la + * factura si tú mismo construyes el nodo XML del complemento y usas el tipo `custom`. + * Es necesario agregar la información del complemento al PDF por separado usando el + * parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Egreso */ + InvoiceEgresoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'E' + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** + * Código del método de pago según el catálogo del SAT. Para facturas de Egreso, + * este campo es opcional y el único valor permitido es `PUE` (Pago en Una sola Exhibición). + * @enum {string} + */ + payment_method?: 'PUE' + /** Documentos relacionados con la nota de crédito. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** + * Conceptos a incluir en la nota de crédito. + * + * El número máximo de elementos que puedes incluir en el comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items?: components['schemas']['LineItemEgresoInput'][] + /** Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. */ + use?: string + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier + * complemento en el comprobante si tú mismo construyes el nodo XML del + * complemento y usas el tipo `custom`. Es necesario agregar la información + * del complemento al PDF por separado usando el parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Pago */ + InvoicePagoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'P' + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Complementos a incluir en la factura. */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Nómina */ + InvoiceNominaEditInput: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'N' + /** Complementos a incluir en la factura. */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonEditInputProperties'] + /** Traslado */ + InvoiceTrasladoEditInput: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'T' + /** + * Conceptos a incluir en el comprobante de Traslado. + * + * El número máximo de elementos que puedes incluir en un comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items?: components['schemas']['LineItemTrasladoInput'][] + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier complemento en + * el comprobante si tú mismo construyes el nodo XML del complemento y usas el tipo + * `custom`. Es necesario agregar la información del complemento al PDF por separado + * usando el parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en + * [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + */ + use?: string + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos + * (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + */ + exchange?: number + /** Documentos relacionados con el comprobante. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonEditInputProperties'] + /** Objeto Receipt */ + Receipt: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['ReceiptProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + } + ReceiptProperties: { + /** + * Format: date-time + * Fecha de emisión del recibo. + */ + date: Date | string + /** + * Format: date-time + * Fecha de expiración en formato ISO8601 (UTC String). + * Es la fecha límite para que el cliente pueda facturar su recibo en el portal de autofactura. + * Se calcula automáticamente a partir de las configuraciones de recibo de la organización. + */ + expires_at: Date | string + /** + * Estado actual del recibo. + * @enum {string} + */ + status?: + 'open' | 'canceled' | 'invoiced_to_customer' | 'invoiced_globally' + /** + * Format: url + * Dirección URL para realizar autofactura. Incluye el `key` del recibo. + * Puedes usarla para generar un botón o un QR de facturación para tus clientes. + */ + self_invoice_url?: string + /** Monto total de la operación */ + total?: number + /** ID de la factura asociada, en caso de estar facturado. */ + invoice?: string + /** ID del cliente asociado al recibo, en caso de haberse asignado. */ + customer?: string + /** Autogenerado. Identificador único alfanumérico corto, útil para acceder a la autofactura desde tu micrositio en factura.space */ + key?: string + /** Conceptos incluidos en el recibo */ + items?: components['schemas']['LineItem'][] + /** Identificador que puedes usar para relacionar este recibo con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + } & components['schemas']['ReceiptEditableProperties'] + ReceiptInput: { + /** Cliente asociado al recibo. Puedes enviar el ID de un cliente existente o un objeto de cliente para crearlo. */ + customer?: string | components['schemas']['CustomerCreateInput'] + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Conceptos a incluir en el recibo. + * + * El número máximo de elementos que puedes incluir en un recibo es de 5,000. Si necesitas + * emitir una recibo con más de 5,000 conceptos, prueba dividir la transacción en varios recibos. + */ + items: components['schemas']['LineItemInput'][] + } & components['schemas']['ReceiptEditableProperties'] & { + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } + ReceiptEditableProperties: { + /** + * Format: date-time + * Fecha de emisión del recibo. Por defecto se utiliza la fecha actual. + */ + date?: Date | string + /** Código que representa la forma de pago, según el [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Autoincremental. Número de folio del recibo para control interno y sin validez fiscal. */ + folio_number?: number + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** Nombre de la sucursal donde se expidió el recibo. */ + branch?: string + /** Identificador opcional que puedes usar para relacionar este recibo con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + } + ReceiptAssignCustomerInput: { + /** Cliente a asignar o reasignar al recibo. Puedes enviar el ID de un cliente existente o un objeto de cliente para crearlo. */ + customer: string | components['schemas']['CustomerCreateInput'] + } + ReceiptSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Receipt'][] + } + InvoiceReceiptInput: { + /** + * Cliente receptor de la factura. Puedes enviarlo como ID de un cliente existente + * o como objeto para crear un cliente nuevo. Si lo omites, el recibo debe tener + * un cliente asignado previamente. + */ + customer?: components['schemas']['CustomerCreateInput'] | string + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default G01 + */ + use?: string + /** Condiciones de pago */ + conditions?: string + } & components['schemas']['InvoiceableCommonInput'] + /** Las fechas son opcionales al seleccionar por periodo. Al enviar receipts se requieren from y to. La periodicidad predeterminada viene de la configuración de la organización. */ + GlobalInvoiceInput: + | (components['schemas']['GlobalInvoiceInputProperties'] & { + receipts?: never + }) + | WithRequired< + components['schemas']['GlobalInvoiceInputProperties'], + 'receipts' | 'from' | 'to' + > + GlobalInvoiceInputProperties: { + /** + * Fecha inicial de los recibos que se incluirán en la factura global. + * Por default, este valor es el inicio del último periodo (día, semana, + * quincena o mes), según el valor de "Periodicidad" (`periodicity`) + * en la configuración de recibos de tu organización. Este valor es requerido cuando se envíe el campo `receipts`. + */ + from?: components['schemas']['DateOrDateTime'] + /** + * Fecha final de los recibos que se incluirán en la factura global. + * Por default, este valor es el fin del último periodo (día, semana, + * quincena o mes), según el valor de "Periodicidad" (`periodicity`) + * en la configuración de recibos de tu organización. Este valor es requerido cuando se envíe el campo `receipts`. + */ + to?: components['schemas']['DateOrDateTime'] + /** + * Periodicidad que corresponde al rango de fechas utilizado. + * Si omites los campos `from` y `to`, las fechas que se asignarán por + * default dependerán del valor de `periodicity`. + * + * Si se omite, se utiliza la periodicidad configurada en los recibos de la organización. + * @enum {string} + */ + periodicity?: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + * + * Si se omite, el mes o bimestre se determina a partir de la fecha inicial y la periodicidad. + */ + months?: string + /** + * Número de folio asignado por la empresa para control interno. + * Si se omite, se asignará el valor autoincremental de la organización. + */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** Fecha de emisión de la factura. Si se omite, se utiliza la fecha final (`to`), limitada a la fecha y hora actuales. */ + date?: components['schemas']['DateOrDateTime'] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). Si se incluye, los recibos se agruparán y se crearán la factura global por la forma de pago. */ + payment_form?: string + /** Recibos a incluir en la factura global. Si se incluye este parámetro, los parámetros `from` y `to` serán requeridos y tendrán que cumplir con el campo `periodicity`. */ + receipts?: string[] + /** + * Permite procesar periodos con más de 5,000 recibos abiertos. Cuando es + * `true`, la factura incluye como máximo 5,000 recibos y los restantes + * conservan el status `"open"`. Repite la solicitud con el mismo periodo + * hasta recibir `null`, que indica que ya no quedan recibos por facturar. + * + * Cuando es `false`, un periodo con más de 5,000 recibos abiertos devuelve + * el error `global_invoice_too_many_items`. + * @default false + */ + limit_to_max_receipts?: boolean + } + ToInvoiceInput: { + /** Lista de keys de recibos que se incluirán en la factura. */ + keys: string[] + /** + * Cliente receptor de la factura. Si lo envías, sobrescribe el cliente + * asignado a los recibos incluidos. Si lo omites, todos los recibos deben + * tener asignado el mismo cliente. Esta regla también aplica cuando + * `dry_run` es `true`. + */ + customer?: components['schemas']['CustomerCreateInput'] | string + /** + * Código de Uso CFDI según catálogo del SAT. + * @default G01 + */ + use?: string + /** + * Si es `true`, sólo valida y regresa un resumen sin crear la factura. + * @default false + */ + dry_run?: boolean + /** Código de forma de pago según el [catálogo del SAT](#forma-de-pago). */ + payment_form?: string | null + } + ToInvoicePreviewInput: { + /** Lista de keys de recibos que se incluirán en la vista previa. */ + keys: string[] + /** + * Cliente opcional para renderizar la vista previa. Si lo omites, + * todos los recibos deben tener asignado el mismo cliente. + */ + customer?: components['schemas']['CustomerCreateInput'] | string | null + /** + * Código de Uso CFDI según catálogo del SAT. + * @default G01 + */ + use?: string + } + /** Resumen de importes e impuestos de los recibos cuando `dry_run=true`. */ + ToInvoiceSummary: { + subtotal: number + discount: number + total: number + receipts: string[] + payment_form: string + item_count: number + taxes: { + totalAdded: number + totalWithholding: number + localTotalAdded: number + localTotalWithholding: number + allAdded: components['schemas']['ReceiptInvoiceSummaryTax'][] + allWithholding: components['schemas']['ReceiptInvoiceSummaryTax'][] + localAllAdded: components['schemas']['ReceiptInvoiceSummaryTax'][] + localAllWithholding: components['schemas']['ReceiptInvoiceSummaryTax'][] + } + } + ReceiptInvoiceSummaryTax: { + type?: string + rate?: number + /** @enum {string} */ + factor: 'Tasa' | 'Cuota' | 'Exento' + withholding: boolean + base: number + amount: number + name?: string + } & { + [key: string]: unknown + } + /** Objeto Retention */ + Retention: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['RetentionReadOnlyProperties'] & + components['schemas']['RetentionProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + } + RetentionReadOnlyProperties: { + /** + * Estado actual de la retención. + * @enum {string} + */ + status?: 'draft' | 'pending' | 'valid' | 'canceled' + /** + * Format: uri + * Dirección URL para verificar el estado de la retención en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la retención. + */ + verification_url?: string + /** + * Tipo de comprobante. + * @enum {string} + */ + type?: 'Retención' + /** + * Format: uuid + * Folio fiscal de la retención, asignado por el SAT. + */ + uuid?: string + stamp?: components['schemas']['Stamp'] | null + customer?: components['schemas']['CustomerInfo'] | null + /** + * Indica si la retención con status `draft` está completa y lista para intentar timbrarse. + * En una retención con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + } + RetentionProperties: { + /** Clave de la retención o información de pagos de acuerdo al catálogo del SAT. */ + cve_retenc?: string + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). + */ + fecha_exp: Date | string | null + /** Si la clave de la retención es “25” (Otro tipo de retenciones), este campo se usa para registrar la descripción de la retención. */ + desc_retenc?: string + /** Identificador alfanumérico para control interno de la empresa y sin relevancia fiscal. */ + folio_int?: string + /** Información sobre el periodo de la retención. */ + periodo?: { + /** Mes inicial del periodo de la retención. */ + mes_ini?: number + /** Mes final del periodo de la retención. */ + mes_fin?: number + /** Año o ejercicio fiscal en que se realizó la retención. */ + ejerc?: number + } + /** Información sobre el total de retenciones efectuadas en el periodo correspondiente. */ + totales?: { + /** Monto total de la operación, con precisión de hasta 6 decimales. */ + monto_tot_operacion?: number + /** Monto total gravado. */ + monto_tot_grav?: number + /** Monto total exento. */ + monto_tot_exent?: number + /** Suma de los montos de impuestos retenidos. */ + monto_tot_ret?: number + /** Colección de impuestos retenidos. */ + imp_retenidos?: { + /** Base del impuesto retenido. */ + base?: number + /** + * Clave del tipo de impuesto retenido, del catálogo del SAT. + * @enum {string} + */ + impuesto?: 'IVA' | 'ISR' + /** Importe del impuesto retenido */ + monto?: number + /** + * - `01`: Pago definitivo IVA + * - `02`: Pago definitivo IEPS + * - `03`: Pago definitivo ISR Plataformas + * - `04`: Pago provisional ISR + * @enum {string} + */ + tipo_pago_ret?: '01' | '02' | '03' | '04' + }[] + } + /** Identificador opcional que puedes usar para relacionar esta retención con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + /** + * Arreglo de complementos a incluir en la factura. Cada elemento contiene + * un `string` con el código XML del complemento. + * @default [] + */ + complements?: components['schemas']['CustomComplementData'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + } + RetentionSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Retention'][] + } + RetentionInput: + | (components['schemas']['RetentionUpdateInput'] & + Record) + | (components['schemas']['RetentionUpdateInput'] & + Record) + RetentionUpdateInput: { + /** + * Estado inicial de la retención. Si se envía `draft`, la retención se + * guardará como borrador y no se timbrará ni se enviará al SAT. También + * al enviar `draft`, `customer`, `cve_retenc`, `periodo` y `totales` + * pueden omitirse o enviarse como `null`. + * @enum {string} + */ + status?: 'draft' + /** Cliente receptor de la factura. */ + customer?: components['schemas']['CustomerCreateInput'] | string | null + /** Clave de la retención o información de pagos de acuerdo al [catálogo del SAT](#clave-de-retencion). */ + cve_retenc?: string | null + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). + */ + fecha_exp?: Date | string + /** Si la clave de la retención es “25” (Otro tipo de retenciones), este campo se usa para registrar la descripción de la retención. */ + desc_retenc?: string + /** Identificador alfanumérico para control interno de la empresa y sin relevancia fiscal. */ + folio_int?: string + /** Información sobre el periodo de la retención. */ + periodo?: { + /** Mes inicial del periodo de la retención. */ + mes_ini: number + /** Mes final del periodo de la retención. */ + mes_fin: number + /** Año o ejercicio fiscal en que se realizó la retención. */ + ejerc: number + } | null + /** Información sobre el total de retenciones efectuadas en el periodo correspondiente. */ + totales?: { + /** Monto total de la operación, con precisión de hasta 6 decimales. */ + monto_tot_operacion: number + /** Monto total gravado. */ + monto_tot_grav?: number + /** Monto total exento. */ + monto_tot_exent: number + /** Suma de los montos de impuestos retenidos. */ + monto_tot_ret?: number + /** Colección de impuestos retenidos. */ + imp_retenidos: { + /** Base del impuesto retenido. */ + base_ret?: number + /** + * Clave del tipo de impuesto retenido, del catálogo del SAT. + * @enum {string} + */ + impuesto?: 'IVA' | 'ISR' + /** Importe del impuesto retenido */ + monto_ret: number + /** + * - `01`: Pago definitivo IVA + * - `02`: Pago definitivo IEPS + * - `03`: Pago definitivo ISR Plataformas + * - `04`: Pago provisional ISR + * @enum {string} + */ + tipo_pago_ret: '01' | '02' | '03' | '04' + }[] + } | null + /** Identificador opcional que puedes usar para relacionar esta retención con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** + * Arreglo de complementos a incluir en la factura. Cada elemento del arreglo deberá contener + * un `string` con el código XML de tu complemento tal cual como quieres que se inserte en el + * XML del CFDI. Sólo se permite un nodo XML raíz por elemento del arreglo. + * @default [] + */ + complements?: components['schemas']['CustomComplementData'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + } + OrganizationAddress: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + OrganizationSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Organization'][] + } + /** Objeto Organization */ + Organization: { + /** ID del objeto */ + id: string + /** + * Format: uri + * URL del logotipo de la organización. + */ + logo_url?: string + /** Zona horaria de la organización, en formato IANA. */ + timezone?: string + /** + * Format: date-time + * Fecha de registro + */ + created_at: Date | string + /** Indica si la organización tiene información necesaria para facturar en ambiente Live. */ + is_production_ready?: boolean + /** Lista de pasos que se necesitan completar para que esta organización pueda emitir facturas válidas en ambiente Live. */ + pending_steps?: { + /** + * Código que representa el tipo de paso que se requiere completar + * @enum {string} + */ + type?: 'legal' | 'logo' | 'certificate' | 'manifiesto' + /** Texto que describe el paso que se requiere completar y que puedes usar para mostrárselo al usuario. */ + description?: string + }[] + /** Datos fiscales de la empresa. */ + legal?: { + /** Nombre comercial de la organización. */ + name?: string + /** Nombre Fiscal o Razón Social de la organización, *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** Código de Régimen Fiscal, del [catálogo del SAT](#régimen-fiscal). */ + tax_system?: string + /** Sitio web de la organización, que se utilizará al enviar la factura por correo electrónico. */ + website?: string + /** Teléfono de la organización, que aparecerá en el PDF de la factura. */ + phone?: string + address?: Record & + components['schemas']['OrganizationAddress'] + } + /** + * Configuración de personalización de la organización, que se utilizarán para reflejar el branding y + * las preferencias de PDFs de la organización. Estos datos se pueden actualizar en cualquier momento. + */ + customization?: { + /** Indica si la organización ya tiene un logotipo cargado. */ + has_logo?: boolean + /** + * Format: hex + * Color distintivo de la marca en representación Hexadecimal RGB de 6 caracteres. + */ + color?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number_test?: number + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia de la organización. */ + pdf_extra?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. Ejemplo: "SON" en lugar de "Sonora" y "MEX" en lugar de "México". + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. Si se desactiva, la firma electrónica sólo se mostrará una vez. + * @default false + */ + repeat_signature?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + /** Información útil sobre el certificado de sello digital (CSD) de la organización, que se utilizará para firmar las facturas. */ + certificate: { + /** Indica si la organización ya tiene el Certificado de Sello Digital (CSD) cargado. */ + has_certificate?: boolean + /** + * Format: date-time + * Fecha de la última actualización del certificado. Se omite cuando no hay un certificado cargado. + */ + updated_at?: Date | string + /** + * Format: date-time + * Fecha de expiración del certificado. Se omite cuando no hay un certificado cargado. + */ + expires_at?: Date | string + /** Número de serie del certificado CSD. */ + serial_number?: string + } + /** Información sobre el certificado FIEL de la organización, que se utiliza para el servicio de descarga masiva de CFDI. */ + fiel: { + /** Indica si la organización ya tiene el Certificado FIEL cargado. */ + has_certificate?: boolean + /** + * Format: date-time + * Fecha de la última actualización del certificado FIEL. Se omite cuando no hay un certificado cargado. + */ + updated_at?: Date | string + /** + * Format: date-time + * Fecha de expiración del certificado FIEL. Se omite cuando no hay un certificado cargado. + */ + expires_at?: Date | string + /** Número de serie del certificado FIEL. */ + serial_number?: string + } + /** Configuración para recibos y la emisión de facturas globales a partir de recibos. */ + receipts?: { + /** + * Periodicidad con la que la empresa decide emitir una factura global + * (al público en general) por todos los recibos que no se hayan facturado. + * Este valor se utiliza como el default al crear una factura global. + * @default month + * @enum {string} + */ + periodicity?: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + /** + * Número máximo de días para facturar a través del portal de autofactura + * después de que se emite el recibo y antes del último día del periodo. + * @default 7 + */ + duration_days?: number + /** + * Número de folio que se asignará al siguiente recibo en ambiente Live. + * Se incrementará automáticamente por cada nuevo recibo. + */ + next_folio_number?: number + /** + * Número de folio que se asignará al siguiente recibo en ambiente Test. + * Se incrementará automáticamente por cada nuevo recibo. + */ + next_folio_number_test?: number + /** + * Indica si la organización genera automáticamente una factura global + * después de cerrar cada periodo configurado. Requiere tener contratado + * el feature de factura global. + * @default false + */ + activate_global_invoice?: boolean + /** + * Agrupa conceptos equivalentes al facturar varios recibos seleccionados, + * incluyendo las autofacturas. No modifica la generación de facturas globales. + * @default false + */ + grouped_items_invoice?: boolean + } + /** Configuraciones para el portal de autofactura, que permite a los clientes facturar sus recibos a través de un micrositio. */ + self_invoice?: { + /** Lista de usos CFDI permitidos para la autofactura. Si este campo está vacío, se permitirán todos los usos CFDI. */ + allowed_cfdi_uses?: string[] + /** + * Indica si la organización aplica el ISR bajo el régimen RESICO. Si es verdadero, el ISR se calculará de acuerdo con el régimen RESICO. + * Si es falso, el ISR se calculará de acuerdo con el régimen general. + */ + apply_resico_isr?: boolean + /** Dirección de correo electrónico para aclaraciones. Aparecerá en el portal de autofacturación. */ + support_email?: string + /** Indica si el correo electrónico de soporte ha sido verificado. Si es falso, el correo electrónico utilizado en el portal de autofacturación será el correo electrónico principal de la cuenta. */ + support_email_verified?: boolean + } + /** + * @deprecated + * Plan heredado de la organización. + */ + plan?: string | null + /** Funcionalidades adicionales contratadas por la organización. */ + add_ons?: string[] + /** Cambio de plan programado, si existe. */ + pending_plan_update?: { + plan?: string + /** Format: date-time */ + scheduled_for?: Date | string + } | null + /** Cambio programado de funcionalidades adicionales, si existe. */ + pending_add_ons_update?: { + add_ons?: string[] + /** Format: date-time */ + scheduled_for?: Date | string + } | null + domain?: string + custom_domain?: string + } + OrganizationDeleteCerts: { + /** + * Format: date-time + * Fecha de eliminación del certificado CSD. + */ + updated_at?: Date | string + } + OrganizationCreateInput: { + /** Nombre comercial de la organización. */ + name: string + } + OrganizationLegalInput: { + /** Nombre comercial de la organización. */ + name: string + /** Nombre Fiscal o Razón Social de la organización, *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name: string + /** Código del Régimen Fiscal, del [catálogo del SAT](#régimen-fiscal). */ + tax_system: string + /** Sitio web de la organización, que aparecerá en el PDF y correos de facturas y recibos. */ + website?: string + /** Dirección de correo electrónico para aclaraciones. Aparecerá en el PDF y correos de facturas y recibos. */ + support_email?: string + /** Teléfono de la organización, que aparecerá en el PDF y correos de facturas y recibos. */ + phone?: string + address: Record & + components['schemas']['OrganizationAddress'] + } + OrganizationCertsInput: { + /** + * Format: binary + * Contenido binario del archivo con extensión `.cer` del certificado CSD. + */ + cer: BinaryInput + /** + * Format: binary + * Contenido binario del archivo con extensión `.key` del certificado CSD. + */ + key: BinaryInput + /** Contraseña de la llave del certificado. */ + password: string + } + OrganizationFielInput: { + /** + * Format: binary + * Contenido binario del archivo con extensión `.cer` de la e.firma (FIEL). + */ + cer: BinaryInput + /** + * Format: binary + * Contenido binario del archivo con extensión `.key` de la e.firma (FIEL). + */ + key: BinaryInput + /** Contraseña de la llave privada de la e.firma (FIEL). */ + password: string + } + OrganizationLogoInput: { + /** + * Format: binary + * Contenido binario del archivo con la imagen que se usará como + * logotipo. Formatos soportados: + * - jpg + * - png + * - svg + */ + file: BinaryInput + } + OrganizationCustomizationInput: { + /** + * Format: hex + * Color distintivo de la marca en representación Hexadecimal RGB de 6 caracteres. + */ + color?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number_test?: number + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia de la organización. */ + pdf_extra?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + OrganizationReceiptsInput: { + /** + * Periodicidad con la que la empresa decide realizar una factura global + * (al público en general) por todos los recibos no facturados. Este + * valor se utiliza como default al crear una factura global. + * @default month + * @enum {string} + */ + periodicity?: 'day' | 'week' | 'fortnight' | 'month' | 'two_months' + /** + * Días máximos para facturar por medio del portal de autofactura + * después de emitido el recibo y antes del último día del periodo + * definido por el atributo `periodicity`. El valor `0` desactiva esta + * opción, haciendo que los recibos expiren siempre el último día del + * periodo. + * @default 7 + */ + duration_days?: number + /** Número de folio que se asignará al siguiente recibo creado en esta organización en ambiente Live. */ + next_folio_number?: number + /** Número de folio que se asignará al siguiente recibo creado en esta organización en ambiente Test. */ + next_folio_number_test?: number + /** + * Activa o desactiva la generación automática de una factura global después + * de cerrar cada periodo configurado. Para activarla, la organización debe + * tener contratado el feature de factura global. + * @default false + */ + activate_global_invoice?: boolean + /** + * Cuando es `true`, agrupa conceptos equivalentes al facturar varios recibos + * seleccionados, incluyendo las autofacturas. No aplica a las facturas globales. + * @default false + */ + grouped_items_invoice?: boolean + } + OrganizationSelfInvoiceInput: { + /** Lista de usos CFDI permitidos para la autofactura. Si este campo está vacío, se permitirán todos los usos CFDI. */ + allowed_cfdi_uses?: string[] + /** + * Indica si la organización aplica el ISR bajo el régimen RESICO. Si es verdadero, el ISR se calculará de acuerdo con el régimen RESICO. + * Si es falso, el ISR se calculará de acuerdo con el régimen general. + */ + apply_resico_isr?: boolean + /** + * Dirección de correo electrónico para aclaraciones. Aparecerá en el portal de autofacturación. + * Al modificarlo se enviará un correo de verificación a la nueva dirección. + */ + support_email?: string + } + /** + * Nombre del dominio. Se permiten caracteres alfanuméricos, sólo minúsculas, + * guión (-) y guión bajo (_). Debe empezar con una letra y + * terminar en letra o número. + */ + DomainField: string + OrganizationDomainInput: { + domain: components['schemas']['DomainField'] + } + OrganizationSeriesCreateInput: { + /** Nombre de la serie. */ + series: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test: number + } + OrganizationSeriesUpdateInput: { + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test?: number + } + OrganizationSeriesDefaultInput: { + /** + * Tipo de comprobante. Valores posibles: + * `I` (Ingreso), `E` (Egreso), `P` (Pago), `N` (Nómina), `T` (Traslado). + * @enum {string} + */ + type: 'I' | 'E' | 'P' | 'N' | 'T' + /** Nombre de la serie. */ + series: string + } + /** Objeto Series */ + OrganizationSeriesGroup: { + /** Nombre de la serie. */ + series?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test?: number + } + OkResponse: { + ok: boolean + } + OrganizationInvite: { + /** Identificador único de la invitación. */ + id?: string + /** + * Format: date-time + * Fecha y hora en que se creó la invitación. + */ + created_at: Date | string + /** + * Format: email + * Correo electrónico al que se envió la invitación. + */ + email?: string + /** Nombre de la organización que envió la invitación. */ + organization_name?: string + /** ID del rol asignado en la invitación, si existe. */ + role?: string | null + /** Nombre del rol asignado en la invitación, si existe. */ + role_name?: string | null + /** Lista de roles visibles que describe el acceso otorgado por la invitación. */ + roles?: string[] + /** + * Format: date-time + * Fecha y hora en que expira la invitación. + */ + expires_at: Date | string | null + } + /** Lista de invitaciones de organización. */ + OrganizationInviteList: components['schemas']['OrganizationInvite'][] + OrganizationPermissionRole: { + /** Identificador único del rol. */ + id?: string + /** Nombre del rol. */ + name?: string + /** Código de plantilla base del rol, si proviene de una plantilla del sistema. */ + template_code?: string | null + /** ID de la organización a la que pertenece el rol. */ + organization?: string | null + /** Número de usuarios que actualmente usan este rol. */ + used_by?: number + /** Operaciones agregadas al rol además de las definidas por su plantilla. */ + overrides_add?: string[] + /** Operaciones removidas del rol respecto a su plantilla. */ + overrides_remove?: string[] + /** Lista final de operaciones permitidas por este rol. */ + operations?: string[] + /** + * Format: date-time + * Fecha y hora de creación del rol. + */ + created_at: Date | string | null + /** + * Format: date-time + * Fecha y hora de la última actualización del rol. + */ + updated_at: Date | string | null + } + /** Lista de roles configurables de la organización. */ + OrganizationPermissionRoleList: components['schemas']['OrganizationPermissionRole'][] + OrganizationPermissionRoleTemplate: { + /** + * Código interno de la plantilla de rol. + * @enum {string} + */ + code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + /** Nombre visible de la plantilla de rol. */ + label?: string + /** Operaciones incluidas por defecto en la plantilla. */ + operations?: string[] + } + /** Lista de plantillas de roles disponibles para la organización. */ + OrganizationPermissionRoleTemplateList: components['schemas']['OrganizationPermissionRoleTemplate'][] + /** Lista de operaciones disponibles para permisos a nivel organización. */ + OrganizationPermissionOperationList: string[] + OrganizationUserAccess: { + /** Identificador del acceso del usuario dentro de la organización. Para el propietario, este valor es `owner` porque su acceso es implícito. */ + id?: string + /** Nombre completo del usuario. */ + full_name?: string + /** + * Format: email + * Correo electrónico del usuario. + */ + email?: string + /** ID del rol asignado al usuario, si existe. Para el propietario, este valor es `null` porque su acceso es implícito. */ + role?: string | null + /** Nombre del rol asignado o del acceso implícito del usuario. Para el propietario, este valor es `owner`. */ + role_name?: string | null + /** ID de la organización a la que pertenece el acceso. */ + organization?: string | null + /** Lista final de operaciones permitidas para el usuario. */ + operations?: string[] + /** + * Format: date-time + * Fecha y hora en que se creó el acceso. Para el propietario, corresponde a la creación de la organización. + */ + created_at: Date | string + /** + * Format: date-time + * Fecha y hora de la última actualización del acceso. Para el propietario, corresponde a la creación de la organización porque su acceso es implícito. + */ + updated_at: Date | string + } + /** Lista de accesos de usuarios a la organización, incluyendo accesos implícitos como el del propietario. */ + OrganizationUserAccessList: components['schemas']['OrganizationUserAccess'][] + OrganizationInviteCreateInput: { + /** + * Format: email + * Correo electrónico del usuario que será invitado. + */ + email: string + /** ID de rol personalizado de la organización. */ + role?: string + } + OrganizationInviteRespondInput: { + /** Indica si la invitación debe aceptarse (`true`) o rechazarse (`false`). */ + accept: boolean + } + OrganizationPermissionRoleCreateInput: { + /** Nombre del rol. */ + name: string + /** + * Código de plantilla base para inicializar el rol, si aplica. + * @enum {string|null} + */ + template_code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + | null + /** Operaciones adicionales que se agregarán al rol. */ + add?: string[] + /** Operaciones que se removerán del rol. */ + remove?: string[] + } + OrganizationPermissionRoleUpdateInput: { + /** Nuevo nombre del rol. */ + name?: string + /** + * Nuevo código de plantilla base del rol, si aplica. + * @enum {string|null} + */ + template_code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + | null + /** Lista completa de operaciones extra que debe conservar el rol. */ + add?: string[] + /** Lista completa de operaciones removidas que debe conservar el rol. */ + remove?: string[] + } + OrganizationUserAccessRoleUpdateInput: { + /** ID del rol que se asignará al usuario. */ + role: string + } + } + responses: { + /** Error en parámetros de la petición */ + BadRequest: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Error de autenticación */ + Unauthenticated: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Conflicto en la petición. La operación que se intenta realizar no puede completarse debido a conflictos en el estado actual del recurso. */ + Conflict: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** No se encontró el recurso especificado. */ + NotFound: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Demasiadas solicitudes en una ventana de tiempo corta. */ + RateLimited: { + headers: { + /** Segundos recomendados antes de reintentar. */ + 'Retry-After'?: number + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Error inesperado */ + UnexpectedError: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Se requiere una suscripción activa y acceso al ambiente Live. */ + InvoiceZipRequestAccessRequired: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** No existen facturas válidas que coincidan con los filtros. */ + InvoiceZipRequestNoInvoices: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** La solicitud no existe o no pertenece a la organización o ambiente actuales. */ + InvoiceZipRequestNotFound: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** La generación del ZIP todavía no ha terminado. */ + InvoiceZipRequestNotReady: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + } + parameters: { + /** Identificador de la solicitud de ZIP. */ + InvoiceZipRequestId: string + /** Objeto con rango de fechas solicitado. */ + SearchDate: components['schemas']['DateRange'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + SearchPage: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + SearchLimit: number + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + SearchPagination: 'page' | 'cursor' + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + SearchAfter: string + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + SearchBefore: string + } + requestBodies: { + CustomerCreate: { + content: { + 'application/json': components['schemas']['CustomerCreateInput'] + } + } + CustomerEdit: { + content: { + 'application/json': components['schemas']['CustomerProperties'] + } + } + ProductCreate: { + content: { + 'application/json': components['schemas']['ProductProperties'] + } + } + ProductEdit: { + content: { + 'application/json': components['schemas']['ProductEditableProperties'] + } + } + InvoiceCreate: { + content: { + 'application/json': components['schemas']['InvoiceCreateInput'] + } + } + InvoiceCreatePending: { + content: { + 'application/json': + | components['schemas']['InvoiceIngresoInput'] + | components['schemas']['InvoiceEgresoInput'] + | components['schemas']['InvoicePagoInput'] + | components['schemas']['InvoiceNominaInput'] + | components['schemas']['InvoiceTrasladoInput'] + } + } + InvoiceEdit: { + content: { + 'application/json': + | components['schemas']['InvoiceIngresoEditInput'] + | components['schemas']['InvoiceEgresoEditInput'] + | components['schemas']['InvoicePagoEditInput'] + | components['schemas']['InvoiceNominaEditInput'] + | components['schemas']['InvoiceTrasladoEditInput'] + } + } + ReceiptCreate: { + content: { + 'application/json': components['schemas']['ReceiptInput'] + } + } + ReceiptAssignCustomer: { + content: { + 'application/json': components['schemas']['ReceiptAssignCustomerInput'] + } + } + ReceiptInvoice: { + content: { + 'application/json': components['schemas']['InvoiceReceiptInput'] + } + } + ReceiptCreateGlobalInvoice: { + content: { + 'application/json': components['schemas']['GlobalInvoiceInput'] + } + } + ReceiptCreateToInvoice: { + content: { + 'application/json': components['schemas']['ToInvoiceInput'] + } + } + ReceiptPreviewToInvoice: { + content: { + 'application/json': components['schemas']['ToInvoicePreviewInput'] + } + } + RetentionCreate: { + content: { + 'application/json': components['schemas']['RetentionInput'] + } + } + RetentionUpdate: { + content: { + 'application/json': components['schemas']['RetentionUpdateInput'] + } + } + OrganizationCreate: { + content: { + 'application/json': components['schemas']['OrganizationCreateInput'] + } + } + OrganizationEditLegal: { + content: { + 'application/json': components['schemas']['OrganizationLegalInput'] + } + } + OrganizationUploadCerts: { + content: { + 'multipart/form-data': components['schemas']['OrganizationCertsInput'] + } + } + OrganizationUploadFiel: { + content: { + 'multipart/form-data': components['schemas']['OrganizationFielInput'] + } + } + OrganizationUploadLogo: { + content: { + 'multipart/form-data': components['schemas']['OrganizationLogoInput'] + } + } + OrganizationEditCustomization: { + content: { + 'application/json': components['schemas']['OrganizationCustomizationInput'] + } + } + OrganizationEditReceiptsSettings: { + content: { + 'application/json': components['schemas']['OrganizationReceiptsInput'] + } + } + OrganizationEditSelfInvoiceSettings: { + content: { + 'application/json': components['schemas']['OrganizationSelfInvoiceInput'] + } + } + OrganizationEditDomain: { + content: { + 'application/json': components['schemas']['OrganizationDomainInput'] + } + } + OrganizationSeriesCreate: { + content: { + 'application/json': components['schemas']['OrganizationSeriesCreateInput'] + } + } + OrganizationSeriesUpdate: { + content: { + 'application/json': components['schemas']['OrganizationSeriesUpdateInput'] + } + } + OrganizationSeriesDefault: { + content: { + 'application/json': components['schemas']['OrganizationSeriesDefaultInput'] + } + } + OrganizationInviteCreate: { + content: { + 'application/json': components['schemas']['OrganizationInviteCreateInput'] + } + } + OrganizationInviteRespond: { + content: { + 'application/json': components['schemas']['OrganizationInviteRespondInput'] + } + } + OrganizationPermissionRoleCreate: { + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleCreateInput'] + } + } + OrganizationPermissionRoleUpdate: { + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleUpdateInput'] + } + } + OrganizationUserAccessRoleUpdate: { + content: { + 'application/json': components['schemas']['OrganizationUserAccessRoleUpdateInput'] + } + } + WebhookCreate: { + content: { + 'application/json': components['schemas']['WebhookCreateInput'] + } + } + WebhookEdit: { + content: { + 'application/json': components['schemas']['WebhookCreateEdit'] + } + } + } + headers: never + pathItems: never +} +export type $defs = Record +export interface operations { + searchCartaPorteAirTransportCodes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `airline_name` o `icao_designator`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchComercioExteriorTariffFractions: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteTransportConfigs: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteRightsOfPassage: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `right_of_passage` o `concessionaire`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteCustomsDocuments: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPortePackagingTypes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteTrailerTypes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteHazardousMaterials: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `description` o `class_division`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteNavalAuthorizations: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchResult'] & { + data?: { + key?: string + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPortePortStations: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `description` o `iata_designator`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteMarineContainers: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listCustomers: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en `legal_name` (nombre fiscal) o en `tax_id` (RFC). */ + q?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['CustomerSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createCustomer: { + parameters: { + query?: { + /** + * Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. + * Además, pasar el valor `true` desactivará la validación de información fiscal con el SAT, + * permitiendo crear clientes con información incompleta. + * Con `true`, el body sigue `CustomerCreateWithEditLinkInput`; en otro caso sigue `CustomerCreateInput`. + */ + createEditLink?: boolean + } + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['CustomerCreate'] + responses: { + /** Un objeto `Customer` con la misma información ya existía */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + /** Nuevo objeto `Customer` creado */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Customer` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editCustomer: { + parameters: { + query?: { + /** + * Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. Pasar el valor `true` al editar + * **no** desactivará la validación de información fiscal con el SAT. + */ + createEditLink?: boolean + } + header?: never + path: { + /** ID del objeto a editar */ + customer_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['CustomerEdit'] + responses: { + /** Objeto `Customer` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Customer` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendEditLinkByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto `Customer` a editar */ + customer_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Correo electrónico del cliente. Si no se proporciona, se usará el correo electrónico del cliente. */ + email?: string + } + } + } + responses: { + /** Enlace de edición enviado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el enlace se envió correctamente */ + ok?: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + validateCustomerTaxInfo: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto `Customer` a validar */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la validación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si la información fiscal del cliente coincide con los registros del SAT */ + is_valid: boolean + /** Detalles de validación fiscal. Es un array vacío cuando `is_valid` es `true`. */ + errors: { + /** + * Indica que Facturapi generó el detalle de validación. + * @enum {string} + */ + source: 'facturapi' + /** Código estable del detalle de validación. */ + code: string + /** Ruta del campo cuya información fiscal no es válida. */ + path?: string + /** Mensaje descriptivo del detalle de validación. */ + message: string + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listProducts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción del producto o SKU. */ + q?: string + /** SKU del producto. */ + sku?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ProductSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createProduct: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ProductCreate'] + responses: { + /** Nuevo objeto `Product` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + product_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Product` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + product_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ProductEdit'] + responses: { + /** Objeto `Product` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + product_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Product` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listInvoices: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** + * Consulta. Texto a buscar en la factura. + * + * La búsqueda se realizará por coincidencias **parciales** en los campos: + * + * - `items[].product.description` + * - `customer.legal_name` + * + * Y por coincidencias **exactas** en los campos: + * + * - `id` + * - `uuid` + * - `customer.tax_id` + * - `folio_number` + * - `total` + */ + q?: string + /** Identificador del cliente. Útil para obtener las facturas emitidas a un sólo cliente. */ + customer?: string + /** Tipo de factura. Búsqueda por tipo de factura con las claves exactas. */ + type?: 'I' | 'E' | 'P' | 'N' | 'T' + /** Método de pago. Búsqueda exacta por método de pago. */ + payment_method?: 'PUE' | 'PPD' + /** Filtrar por folio de la factura. Coincidencia exacta. */ + folio_number?: number + /** Filtrar por serie de la factura. Coincidencia exacta. */ + series?: string + /** Filtrar por identificador externo. Coincidencia exacta. */ + external_id?: string + /** Filtrar por tipo de emisión. */ + issuer_type?: components['schemas']['IssuingType'] + /** Filtrar por uno o más estados de cancelación. */ + cancellation_status?: components['schemas']['CancellationStatus'][] + /** Filtrar por el UUID del CFDI. Coincidencia exacta. */ + uuid?: string + /** Filtrar por estado de pago. Coincidencia exacta. */ + payment_status?: 'paid' | 'unpaid' + /** Objeto con rango de fechas solicitado. El rango filtra el campo `date` de la factura. */ + date?: components['schemas']['DateRange'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createInvoice: { + parameters: { + query?: { + /** + * Útil para facturas de gran tamaño. Si se envía `false` o no se envía, la llamada esperará a que el SAT responda timbrando la factura. + * Si se envía `true`, la llamada regresará inmediatamente con el objeto `invoice` en status `pending`, y podrá consultarse su cambio de status + * a `valid` en un momento posterior. + */ + async?: boolean + } + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceCreate'] + responses: { + /** Nuevo objeto `Invoice` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | components['schemas']['Invoice'] + | components['schemas']['InvoiceDraft'] + } + } + /** Solicitud aceptada; Facturapi intentará recuperar el CFDI hasta cinco veces, una cada 10 minutos */ + 202: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] & { + /** @enum {string} */ + status: 'pending' + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDraftInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + invoice_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** Objeto `Invoice` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceDraft'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelInvoice: { + parameters: { + query?: { + /** + * Requerido para documentos emitidos; omite los parámetros para eliminar un borrador. + * Clave que representa el motivo de la cancelación de la factura. + * + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra factura. + * - `03`: **No se llevó a cabo la operación**. Cuando la venta o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la factura global**. Cuando se requiere cancelar + * una factura al público en general porque el cliente solicita su comprobante. + */ + motive?: '01' | '02' | '03' | '04' + /** + * ID de la factura que sustituye a la factura que se está cancelando. + * + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + */ + substitution?: string + } + header?: never + path: { + /** ID de la factura a cancelar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Solicitud de cancelación exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + copyToDraftInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID de la factura a copiar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Nuevo objeto `Invoice` con status `draft`. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceDraft'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + stampDraftInvoice: { + parameters: { + query?: { + /** + * Útil para facturas de gran tamaño. Si se envía `false` o no se envía, la llamada esperará a que el SAT responda timbrando la factura. + * Si se envía `true`, la llamada regresará inmediatamente con el objeto `invoice` en status `pending`, y podrá consultarse su cambio de status + * a `valid` en un momento posterior. + */ + async?: boolean + } + header?: never + path: { + /** ID del objeto a timbrar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` timbrado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateInvoiceStatus: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto invoice a actualizar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoicePaymentSummary: { + parameters: { + query: { + /** Monto que se paga de esta factura, expresado en la divisa de la factura. No puede exceder el saldo pendiente. */ + amount: number + } + header?: never + path: { + /** ID de la factura de ingreso (método de pago PPD) que se desea pagar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Resumen del documento relacionado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** UUID de la factura */ + uuid: string + /** Folio de la factura. Se omite si la factura no lo tiene registrado. */ + folio_number?: number + /** Serie de la factura */ + series: string | null + /** Número de parcialidad que corresponde a este pago */ + installment: number + /** Saldo pendiente de la factura antes de aplicar este pago */ + last_balance: number + /** Total de la factura */ + total: number + /** Divisa de la factura */ + currency: string + /** Monto que se paga en esta parcialidad */ + amount: number + /** Impuestos de la factura prorrateados al monto pagado */ + taxes: { + /** Base del impuesto prorrateada al monto pagado */ + base: number + /** Tasa o cuota del impuesto */ + rate: number + /** + * Tipo de impuesto (IVA, ISR, etc.) + * @enum {string} + */ + type: 'IVA' | 'ISR' | 'IEPS' + /** + * Tipo de factor (Tasa, Exento, etc.) + * @enum {string} + */ + factor: 'Tasa' | 'Cuota' | 'Exento' + /** Indica si se trata de una retención */ + withholding: boolean + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + previewInvoicePdf: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** El archivo PDF de la factura */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/pdf': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + previewInvoicePdfUrl: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del comprobante CFDI en el formato solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoiceDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'pdf' | 'xml' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadCancellationReceiptXml: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del acuse de recibo de cancelación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getCancellationReceiptDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del acuse de cancelación */ + format: 'xml' | 'pdf' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendInvoiceByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar la factura. Si no se envía este parámetro, la factura será enviada al correo que el cliente tenga registrado. */ + email?: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listInvoiceZipRequests: { + parameters: { + query?: { + /** Año a filtrar. Debe enviarse junto con `month`. */ + year?: number + /** Mes a filtrar. Debe enviarse junto con `year`. */ + month?: number + /** Status de la solicitud. */ + status?: components['schemas']['InvoiceZipRequestStatus'] + /** Filtra facturas emitidas o recibidas. */ + issuer_type?: components['schemas']['IssuingType'] + /** Filtra por un tipo de factura o por un arreglo normalizado exacto. */ + invoice_types?: components['schemas']['InvoiceZipRequestInvoiceType'][] + /** Página de resultados, empezando en 1. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado paginado de solicitudes de ZIP. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequestSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceZipRequestCreateInput'] + } + } + responses: { + /** Solicitud de ZIP creada o recuperada correctamente. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequest'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNoInvoices'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + retrieveInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Solicitud de ZIP recuperada correctamente. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequest'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo ZIP generado. */ + 200: { + headers: { + /** Nombre sugerido con formato `attachment; filename="YYYY-MM.zip"`. */ + 'Content-Disposition'?: string + [name: string]: unknown + } + content: { + 'application/zip': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 409: components['responses']['InvoiceZipRequestNotReady'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoiceZipRequestDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 409: components['responses']['InvoiceZipRequestNotReady'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listReceipts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de los conceptos del recibo o el SKU. */ + q?: string + /** ID del cliente asociado al recibo. */ + customer?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). Si se incluye, los recibos se agruparán y se listarán de acuerdo a la forma de pago. */ + payment_form?: string + /** Fecha de creación mayor o igual a la especificada. */ + 'date[gte]'?: Date | string + /** Fecha de creación menor o igual a la especificada. */ + 'date[lte]'?: Date | string + /** ID de la factura relacionada al recibo. */ + invoice?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ReceiptSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createReceipt: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreate'] + responses: { + /** Nuevo objeto `Receipt` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Receipt` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + assignReceiptCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a actualizar */ + receipt_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ReceiptAssignCustomer'] + responses: { + /** Objeto `Receipt` actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a cancelar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto 'Receipt' cancelado exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + invoiceReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a facturar */ + receipt_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ReceiptInvoice'] + responses: { + /** Nuevo objeto `Invoice` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createToInvoiceFromReceipts: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreateToInvoice'] + responses: { + /** Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | components['schemas']['Invoice'] + | components['schemas']['ToInvoiceSummary'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 500: components['responses']['UnexpectedError'] + } + } + previewToInvoiceFromReceipts: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptPreviewToInvoice'] + responses: { + /** Contenido binario del PDF */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/pdf': BinaryInput + } + } + /** No se encontraron recibos elegibles para las keys enviadas */ + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 500: components['responses']['UnexpectedError'] + } + } + previewToInvoiceFromReceiptsUrl: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptPreviewToInvoice'] + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createGlobalInvoice: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreateGlobalInvoice'] + responses: { + /** Nuevo objeto `Invoice` creado, o `null` si no hay recibos abiertos en el periodo */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] | null + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadReceiptPdf: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del recibo digital en formato PDF */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getReceiptDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendReceiptByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + receipt_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar el recibo digital. */ + email: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listRetentions: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en el nombre fiscal del cliente o su RFC. */ + q?: string + /** Identificador del cliente. Útil para obtener las retenciones emitidas a un sólo cliente. */ + customer?: string + /** Filtrar por uno o más estados de retención. Si se omite, no se filtra por estado, equivalente a `all`. Enviar `all` también desactiva este filtro. */ + status?: ( + 'all' | 'draft' | 'pending' | 'valid' | 'canceled' | 'failed' + )[] + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['RetentionSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createRetention: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['RetentionCreate'] + responses: { + /** Nuevo objeto `Retention` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a editar */ + retention_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['RetentionUpdate'] + responses: { + /** Objeto `Retention` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelRetention: { + parameters: { + query?: { + /** + * Clave que representa el motivo de la cancelación de la retención. + * Requerido para retenciones que no son borrador. + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra retención. + * - `03`: **No se llevó a cabo la operación**. Cuando la operación o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la retención global**. Cuando se requiere cancelar + * una retención al público en general porque el cliente solicita su comprobante. + */ + motive?: '01' | '02' | '03' | '04' + /** + * ID de la retención que sustituye a la retención que se está cancelando + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + */ + substitution?: string + } + header?: never + path: { + /** ID de la retención a cancelar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` cancelado exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + copyToDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a copiar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Nuevo objeto `Retention` con status `draft`. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + stampDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a timbrar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` timbrado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + retention_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del comprobante CFDI en el formato solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryInput + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getRetentionDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + retention_id: string + /** Formato del archivo de descarga */ + format: 'pdf' | 'xml' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendRetentionByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + retention_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar la retención. Si no se envía este parámetro, la retención será enviada al correo que el cliente tenga registrado. */ + email?: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizations: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en `name` (nombre comercial), `legal_name` (nombre fiscal) o en `tax_id` (RFC). */ + q?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganization: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['OrganizationCreate'] + responses: { + /** Nuevo objeto `Organization` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + meOrganization: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganization: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganization: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationLegal: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditLegal'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationCertificate: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadCerts'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationCertificate: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationDeleteCerts'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationFiel: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización. También puedes usar `me` con la Live Secret Key de la organización. */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadFiel'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationLogo: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadLogo'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationCustomization: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditCustomization'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationReceiptsSettings: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditReceiptsSettings'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationSelfInvoiceSettings: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditSelfInvoiceSettings'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + checkDomainAvailability: { + parameters: { + query: { + domain: components['schemas']['DomainField'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Información de disponibilidad de dominio */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el dominio está diponible */ + available: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationDomain: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditDomain'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getTestApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Test API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + renewTestApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Test API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listLiveApiKeys: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Primeros 12 caracteres de la llave secreta */ + first_12: string + /** + * Format: date-time + * Fecha de creación de la llave secreta + */ + created_at: Date | string + /** ID de la llave secreta */ + id: string + }[] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + renewLiveApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteLiveApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID de la llave secreta a eliminar */ + id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Primeros 12 caracteres de la llave secreta */ + first_12?: string + /** + * Format: date-time + * Fecha de creación de la llave secreta + */ + created_at?: Date | string + /** ID de la llave secreta */ + id?: string + }[] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Listado de objetos `Series` creadas previamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data?: components['schemas']['OrganizationSeriesGroup'][] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesCreate'] + responses: { + /** Nuevo objeto de la `Serie` creada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDefaultSeries: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesDefault'] + responses: { + /** Serie predeterminada actualizada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 500: components['responses']['UnexpectedError'] + } + } + updateSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Nombre de la serie */ + series_name: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesUpdate'] + responses: { + /** Objeto `Serie` editada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Nombre de la serie */ + series_name: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Serie` eliminado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationTeam: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de accesos de usuarios dentro de la organización, incluyendo accesos implícitos como el del propietario */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccessList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationTeamInvites: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de invitaciones enviadas y aún vigentes para la organización */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInviteList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganizationTeamInvite: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationInviteCreate'] + responses: { + /** Invitación creada o actualizada para el correo solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInvite'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationTeamUser: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Detalle del acceso del usuario dentro de la organización, incluyendo accesos implícitos como el del propietario */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccess'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + removeOrganizationUserAccess: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Usuario removido de la organización */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationTeamInvite: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Clave pública de la invitación. */ + invite_key: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Invitación cancelada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listPendingOrganizationInvites: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Lista de invitaciones recibidas por el usuario autenticado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInviteList'] + } + } + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + respondOrganizationInvite: { + parameters: { + query?: never + header?: never + path: { + /** Clave pública de la invitación. */ + invite_key: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationInviteRespond'] + responses: { + /** Invitación aceptada o rechazada exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionRoles: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de roles */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationPermissionRoleCreate'] + responses: { + /** Rol creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionRoleTemplates: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Plantillas disponibles */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleTemplateList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionOperations: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de códigos de operación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionOperationList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Detalle del rol */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationPermissionRoleUpdate'] + responses: { + /** Rol actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Rol eliminado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateOrganizationTeamUserRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUserAccessRoleUpdate'] + responses: { + /** Acceso del usuario actualizado con el nuevo rol */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccess'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listWebhooks: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WebhookSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createWebhook: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['WebhookCreate'] + responses: { + /** Nuevo objeto `Webhook` creado */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + webhook_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Webhook` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + webhook_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['WebhookEdit'] + responses: { + /** Objeto `Webhook` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + webhook_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Webhook` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + validateWebhookSignature: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': { + /** Llave secreta del webhook. Se obtiene al crear un webhook o desde el dashboard de Facturapi. */ + secret: string + /** Payload firmado. Prefiere el texto JSON original, conservando exactamente los bytes recibidos. También se aceptan objetos, pero la verificación utiliza su serialización JSON. */ + payload: + | string + | { + [key: string]: unknown + } + /** Firma del webhook recibida en el header `Facturapi-Signature` */ + signature: string + } + } + } + responses: { + /** Payload original con firma válida */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | string + | { + [key: string]: unknown + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + checkApiHealth: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** La API está operando con normalidad. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + ok?: boolean + } + } + } + /** Error de autenticación. Asegúrate de estar usando tu llave secreta. */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** Servicio temporalmente no disponible. */ + 502: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + validateTaxId: { + parameters: { + query: { + tax_id: string + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la validación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['TaxIdValidationResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchProducts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de la clasificación. */ + q?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ProductCatalogSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchUnits: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de la unidad de medida. */ + q?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['UnitCatalogSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + onInvoiceGlobalInvoiceCreated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceGlobalInvoiceCreatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceCreatedFromDashboard: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceCreatedFromDashboardEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceCancellationStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceCancellationStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onReceiptSelfInvoiceComplete: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['ReceiptSelfInvoiceCompleteEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onReceiptStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['ReceiptStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onCustomerEditLinkCompleted: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['CustomerEditLinkCompletedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } +} +type WithRequired = T & { + [P in K]-?: T[P] +} diff --git a/src/generated/models.ts b/src/generated/models.ts new file mode 100644 index 0000000..b838573 --- /dev/null +++ b/src/generated/models.ts @@ -0,0 +1,360 @@ +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as Input } from './input' +import type { components as Output } from './output' +export type DateOrDateTime = Output['schemas']['DateOrDateTime'] +export type InvoiceGlobalInvoiceCreatedEvent = + Output['schemas']['InvoiceGlobalInvoiceCreatedEvent'] +export type InvoiceStatusUpdatedEvent = + Output['schemas']['InvoiceStatusUpdatedEvent'] +export type InvoiceCreatedFromDashboardEvent = + Output['schemas']['InvoiceCreatedFromDashboardEvent'] +export type InvoiceCancellationStatusUpdatedEvent = + Output['schemas']['InvoiceCancellationStatusUpdatedEvent'] +export type ReceiptSelfInvoiceCompleteEvent = + Output['schemas']['ReceiptSelfInvoiceCompleteEvent'] +export type ReceiptStatusUpdatedEvent = + Output['schemas']['ReceiptStatusUpdatedEvent'] +export type CustomerEditLinkCompletedEvent = + Output['schemas']['CustomerEditLinkCompletedEvent'] +export type SearchKeyDescriptionResult = + Output['schemas']['SearchKeyDescriptionResult'] +export type RelatedResourceMessage = Output['schemas']['RelatedResourceMessage'] +export type EventBase = Output['schemas']['EventBase'] +export type DateRange = Output['schemas']['DateRange'] +export type GenericError = Output['schemas']['GenericError'] +export type ErrorDetail = Output['schemas']['ErrorDetail'] +export type ResourceAutoGeneratedProps = + Output['schemas']['ResourceAutoGeneratedProps'] +export type TaxIdValidationResult = Output['schemas']['TaxIdValidationResult'] +export type ProductCatalogResult = Output['schemas']['ProductCatalogResult'] +export type UnitCatalogResult = Output['schemas']['UnitCatalogResult'] +export type ProductCatalogSearchResult = + Output['schemas']['ProductCatalogSearchResult'] +export type UnitCatalogSearchResult = + Output['schemas']['UnitCatalogSearchResult'] +export type BaseTax = Output['schemas']['BaseTax'] +export type IepsTax = Output['schemas']['IepsTax'] +export type Stamp = Output['schemas']['Stamp'] +export type LineItem = Output['schemas']['LineItem'] +export type ThirdParty = Output['schemas']['ThirdParty'] +export type LineItemInput = Input['schemas']['LineItemInput'] +export type LineItemEgresoInput = Input['schemas']['LineItemEgresoInput'] +export type LineItemTrasladoInput = Input['schemas']['LineItemTrasladoInput'] +export type HidroYPetroComplementInput = + Input['schemas']['HidroYPetroComplementInput'] +export type IeduComplementInput = Input['schemas']['IeduComplementInput'] +export type CustomComplementData = Output['schemas']['CustomComplementData'] +export type CustomComplementProperties = + Output['schemas']['CustomComplementProperties'] +export type CustomComplementInput = Input['schemas']['CustomComplementInput'] +export type NominaComplementDataInput = + Input['schemas']['NominaComplementDataInput'] +export type NominaComplementDataProperties = + Output['schemas']['NominaComplementDataProperties'] +export type NominaComplementDataDirectProperties = + Output['schemas']['NominaComplementDataDirectProperties'] +export type NominaComplementDataNestedInput = + Input['schemas']['NominaComplementDataNestedInput'] +export type NominaComplementDataNestedProperties = + Output['schemas']['NominaComplementDataNestedProperties'] +export type NominaIncapacidadInput = Input['schemas']['NominaIncapacidadInput'] +export type NominaIncapacidadProperties = + Output['schemas']['NominaIncapacidadProperties'] +export type NominaOtroPagoInput = Input['schemas']['NominaOtroPagoInput'] +export type NominaOtroPagoDirectProperties = + Output['schemas']['NominaOtroPagoDirectProperties'] +export type NominaCompensacionInput = + Input['schemas']['NominaCompensacionInput'] +export type NominaCompensacionProperties = + Output['schemas']['NominaCompensacionProperties'] +export type NominaDeduccionInput = Input['schemas']['NominaDeduccionInput'] +export type NominaDeduccionProperties = + Output['schemas']['NominaDeduccionProperties'] +export type NominaPercepcionesInput = + Input['schemas']['NominaPercepcionesInput'] +export type NominaPercepcionesProperties = + Output['schemas']['NominaPercepcionesProperties'] +export type NominaSeparacionInput = Input['schemas']['NominaSeparacionInput'] +export type NominaSeparacionProperties = + Output['schemas']['NominaSeparacionProperties'] +export type NominaJubilacionInput = Input['schemas']['NominaJubilacionInput'] +export type NominaJubilacionProperties = + Output['schemas']['NominaJubilacionProperties'] +export type NominaPercepcionProperties = + Output['schemas']['NominaPercepcionProperties'] +export type NominaPercepcionInput = Input['schemas']['NominaPercepcionInput'] +export type NominaPercepcionDirectProperties = + Output['schemas']['NominaPercepcionDirectProperties'] +export type NominaPercepcionNestedInput = + Input['schemas']['NominaPercepcionNestedInput'] +export type NominaPercepcionNestedProperties = + Output['schemas']['NominaPercepcionNestedProperties'] +export type NominaHorasExtraInput = Input['schemas']['NominaHorasExtraInput'] +export type NominaHorasExtraProperties = + Output['schemas']['NominaHorasExtraProperties'] +export type NominaAccionesInput = Input['schemas']['NominaAccionesInput'] +export type NominaAccionesProperties = + Output['schemas']['NominaAccionesProperties'] +export type NominaReceptorProperties = + Output['schemas']['NominaReceptorProperties'] +export type NominaReceptorInput = Input['schemas']['NominaReceptorInput'] +export type NominaReceptorDirectProperties = + Output['schemas']['NominaReceptorDirectProperties'] +export type NominaReceptorNestedProperties = + Output['schemas']['NominaReceptorNestedProperties'] +export type NominaReceptorNestedInput = + Input['schemas']['NominaReceptorNestedInput'] +export type NominaSubContratacionRequiredProperties = + Output['schemas']['NominaSubContratacionRequiredProperties'] +export type NominaSubContratacionProperties = + Output['schemas']['NominaSubContratacionProperties'] +export type NominaEntidadSncfInput = Input['schemas']['NominaEntidadSncfInput'] +export type NominaEmisorInput = Input['schemas']['NominaEmisorInput'] +export type NominaEmisorProperties = Output['schemas']['NominaEmisorProperties'] +export type PagoOrCustomComplementProperties = + Output['schemas']['PagoOrCustomComplementProperties'] +export type PagoOrCustomComplementInput = + Input['schemas']['PagoOrCustomComplementInput'] +export type PagoComplementProperties = + Output['schemas']['PagoComplementProperties'] +export type PagoComplementInput = Input['schemas']['PagoComplementInput'] +export type InvoiceComplementInput = Input['schemas']['InvoiceComplementInput'] +export type InvoiceComplementProperties = + Output['schemas']['InvoiceComplementProperties'] +export type PagoComplementDataProperties = + Output['schemas']['PagoComplementDataProperties'] +export type PaymentProperties = Output['schemas']['PaymentProperties'] +export type PagoComplementDataInput = + Input['schemas']['PagoComplementDataInput'] +export type NominaOrCustomComplementProperties = + Output['schemas']['NominaOrCustomComplementProperties'] +export type NominaOrCustomComplementInput = + Input['schemas']['NominaOrCustomComplementInput'] +export type NominaComplementProperties = + Output['schemas']['NominaComplementProperties'] +export type NominaComplementInput = Input['schemas']['NominaComplementInput'] +export type CartaPorteProperties = Output['schemas']['CartaPorteProperties'] +export type CartaPorteInput = Input['schemas']['CartaPorteInput'] +export type ComercioExteriorProperties = + Output['schemas']['ComercioExteriorProperties'] +export type ComercioExteriorInput = Input['schemas']['ComercioExteriorInput'] +export type LeyendasFiscalesProperties = + Output['schemas']['LeyendasFiscalesProperties'] +export type LeyendasFiscalesInput = Input['schemas']['LeyendasFiscalesInput'] +export type CartaPorteOrCustomComplementProperties = + Output['schemas']['CartaPorteOrCustomComplementProperties'] +export type CartaPorteOrCustomComplementInput = + Input['schemas']['CartaPorteOrCustomComplementInput'] +export type LeyendasFiscalesData = Output['schemas']['LeyendasFiscalesData'] +export type CartaPorteDataProperties = + Output['schemas']['CartaPorteDataProperties'] +export type CartaPorteDataInput = Input['schemas']['CartaPorteDataInput'] +export type ComercioExteriorDataProperties = + Output['schemas']['ComercioExteriorDataProperties'] +export type ComercioExteriorDataInput = + Input['schemas']['ComercioExteriorDataInput'] +export type ComercioExteriorDomicilio = + Output['schemas']['ComercioExteriorDomicilio'] +export type ComercioExteriorEmisor = Output['schemas']['ComercioExteriorEmisor'] +export type ComercioExteriorPropietario = + Output['schemas']['ComercioExteriorPropietario'] +export type ComercioExteriorReceptor = + Output['schemas']['ComercioExteriorReceptor'] +export type ComercioExteriorDestinatario = + Output['schemas']['ComercioExteriorDestinatario'] +export type ComercioExteriorDescripcionesEspecificas = + Output['schemas']['ComercioExteriorDescripcionesEspecificas'] +export type ComercioExteriorMercancia = + Output['schemas']['ComercioExteriorMercancia'] +export type ComercioExteriorMercancias = + Output['schemas']['ComercioExteriorMercancias'] +export type CartaPorteCantidadTransporta = + Output['schemas']['CartaPorteCantidadTransporta'] +export type CartaPorteDetalleMercancia = + Output['schemas']['CartaPorteDetalleMercancia'] +export type CartaPorteDocumentacionAduanera = + Output['schemas']['CartaPorteDocumentacionAduanera'] +export type CartaPorteGuiaIdentificacion = + Output['schemas']['CartaPorteGuiaIdentificacion'] +export type CartaPorteMercancia = Output['schemas']['CartaPorteMercancia'] +export type CartaPorteIdentificacionVehicular = + Output['schemas']['CartaPorteIdentificacionVehicular'] +export type CartaPorteSeguros = Output['schemas']['CartaPorteSeguros'] +export type CartaPorteRemolque = Output['schemas']['CartaPorteRemolque'] +export type CartaPorteAutotransporte = + Output['schemas']['CartaPorteAutotransporte'] +export type CartaPorteContenedorMaritimo = + Output['schemas']['CartaPorteContenedorMaritimo'] +export type CartaPorteTransporteMaritimo = + Output['schemas']['CartaPorteTransporteMaritimo'] +export type CartaPorteTransporteAereo = + Output['schemas']['CartaPorteTransporteAereo'] +export type CartaPorteDerechosDePaso = + Output['schemas']['CartaPorteDerechosDePaso'] +export type CartaPorteContenedorFerroviario = + Output['schemas']['CartaPorteContenedorFerroviario'] +export type CartaPorteCarroFerroviario = + Output['schemas']['CartaPorteCarroFerroviario'] +export type CartaPorteTransporteFerroviario = + Output['schemas']['CartaPorteTransporteFerroviario'] +export type CartaPorteDomicilio = Output['schemas']['CartaPorteDomicilio'] +export type CartaPorteMercancias = Output['schemas']['CartaPorteMercancias'] +export type NamespaceRequiredProperties = + Output['schemas']['NamespaceRequiredProperties'] +export type NamespaceProperties = Output['schemas']['NamespaceProperties'] +export type CommonAddressProperties = + Output['schemas']['CommonAddressProperties'] +export type WebhookSearchResult = Output['schemas']['WebhookSearchResult'] +export type WebhookProperties = Output['schemas']['WebhookProperties'] +export type WebhookCreateInput = Input['schemas']['WebhookCreateInput'] +export type WebhookCreateEdit = Output['schemas']['WebhookCreateEdit'] +export type CustomerSearchResult = Output['schemas']['CustomerSearchResult'] +export type CustomerNonEditableProperties = + Output['schemas']['CustomerNonEditableProperties'] +export type CustomerProperties = Output['schemas']['CustomerProperties'] +export type CustomerCommonProperties = + Output['schemas']['CustomerCommonProperties'] +export type CancellationQueryInput = Input['schemas']['CancellationQueryInput'] +export type CustomerCreateWithEditLinkInput = + Input['schemas']['CustomerCreateWithEditLinkInput'] +export type CustomerCreateCommonInput = + Input['schemas']['CustomerCreateCommonInput'] +export type CustomerNationalAddressInput = + Input['schemas']['CustomerNationalAddressInput'] +export type CustomerForeignAddressInput = + Input['schemas']['CustomerForeignAddressInput'] +export type CustomerNationalCreateInput = + Input['schemas']['CustomerNationalCreateInput'] +export type CustomerForeignCreateInput = + Input['schemas']['CustomerForeignCreateInput'] +export type CustomerGenericCreateInput = + Input['schemas']['CustomerGenericCreateInput'] +export type CustomerCreateInput = Input['schemas']['CustomerCreateInput'] +export type LineItemProductInput = Input['schemas']['LineItemProductInput'] +export type LineItemProductEgresoInput = + Input['schemas']['LineItemProductEgresoInput'] +export type LineItemTrasladoProductInput = + Input['schemas']['LineItemTrasladoProductInput'] +export type LineItemProduct = Output['schemas']['LineItemProduct'] +export type Parts = Output['schemas']['Parts'] +export type PartInput = Input['schemas']['PartInput'] +export type ProductSearchResult = Output['schemas']['ProductSearchResult'] +export type ProductProperties = Output['schemas']['ProductProperties'] +export type ProductEditableProperties = + Output['schemas']['ProductEditableProperties'] +export type ProductEgresoProperties = + Output['schemas']['ProductEgresoProperties'] +export type PaymentInput = Input['schemas']['PaymentInput'] +export type CustomerComercioExterior = + Output['schemas']['CustomerComercioExterior'] +export type RelatedDocumentInput = Input['schemas']['RelatedDocumentInput'] +export type InvoiceZipRequestStatus = + Output['schemas']['InvoiceZipRequestStatus'] +export type InvoiceZipRequestInvoiceType = + Output['schemas']['InvoiceZipRequestInvoiceType'] +export type InvoiceZipRequestCreateInput = + Input['schemas']['InvoiceZipRequestCreateInput'] +export type InvoiceZipRequest = Output['schemas']['InvoiceZipRequest'] +export type InvoiceZipRequestSearchResult = + Output['schemas']['InvoiceZipRequestSearchResult'] +export type InvoiceDraft = Output['schemas']['InvoiceDraft'] +export type InvoiceSearchResult = Output['schemas']['InvoiceSearchResult'] +export type InvoiceRequiredProperties = + Output['schemas']['InvoiceRequiredProperties'] +export type InvoiceProperties = Output['schemas']['InvoiceProperties'] +export type InvoiceDraftProperties = Output['schemas']['InvoiceDraftProperties'] +export type InvoiceableCommonInput = Input['schemas']['InvoiceableCommonInput'] +export type InvoiceableCommonEditInput = + Input['schemas']['InvoiceableCommonEditInput'] +export type InvoiceCustomerInput = Input['schemas']['InvoiceCustomerInput'] +export type InvoiceCommonInputProperties = + Output['schemas']['InvoiceCommonInputProperties'] +export type InvoiceCommonEditInputProperties = + Output['schemas']['InvoiceCommonEditInputProperties'] +export type InvoiceDraftInputProperties = + Output['schemas']['InvoiceDraftInputProperties'] +export type InvoiceCreateInput = Input['schemas']['InvoiceCreateInput'] +export type InvoiceIngresoInput = Input['schemas']['InvoiceIngresoInput'] +export type InvoiceEgresoInput = Input['schemas']['InvoiceEgresoInput'] +export type InvoicePagoInput = Input['schemas']['InvoicePagoInput'] +export type InvoiceNominaInput = Input['schemas']['InvoiceNominaInput'] +export type InvoiceTrasladoInput = Input['schemas']['InvoiceTrasladoInput'] +export type InvoiceIngresoEditInput = + Input['schemas']['InvoiceIngresoEditInput'] +export type InvoiceEgresoEditInput = Input['schemas']['InvoiceEgresoEditInput'] +export type InvoicePagoEditInput = Input['schemas']['InvoicePagoEditInput'] +export type InvoiceNominaEditInput = Input['schemas']['InvoiceNominaEditInput'] +export type InvoiceTrasladoEditInput = + Input['schemas']['InvoiceTrasladoEditInput'] +export type ReceiptProperties = Output['schemas']['ReceiptProperties'] +export type ReceiptInput = Input['schemas']['ReceiptInput'] +export type ReceiptEditableProperties = + Output['schemas']['ReceiptEditableProperties'] +export type ReceiptAssignCustomerInput = + Input['schemas']['ReceiptAssignCustomerInput'] +export type ReceiptSearchResult = Output['schemas']['ReceiptSearchResult'] +export type InvoiceReceiptInput = Input['schemas']['InvoiceReceiptInput'] +export type GlobalInvoiceInput = Input['schemas']['GlobalInvoiceInput'] +export type GlobalInvoiceInputProperties = + Output['schemas']['GlobalInvoiceInputProperties'] +export type ToInvoiceInput = Input['schemas']['ToInvoiceInput'] +export type ToInvoicePreviewInput = Input['schemas']['ToInvoicePreviewInput'] +export type ToInvoiceSummary = Output['schemas']['ToInvoiceSummary'] +export type ReceiptInvoiceSummaryTax = + Output['schemas']['ReceiptInvoiceSummaryTax'] +export type RetentionReadOnlyProperties = + Output['schemas']['RetentionReadOnlyProperties'] +export type RetentionProperties = Output['schemas']['RetentionProperties'] +export type RetentionSearchResult = Output['schemas']['RetentionSearchResult'] +export type RetentionInput = Input['schemas']['RetentionInput'] +export type RetentionUpdateInput = Input['schemas']['RetentionUpdateInput'] +export type OrganizationAddress = Output['schemas']['OrganizationAddress'] +export type OrganizationSearchResult = + Output['schemas']['OrganizationSearchResult'] +export type OrganizationDeleteCerts = + Output['schemas']['OrganizationDeleteCerts'] +export type OrganizationCreateInput = + Input['schemas']['OrganizationCreateInput'] +export type OrganizationLegalInput = Input['schemas']['OrganizationLegalInput'] +export type OrganizationCertsInput = Input['schemas']['OrganizationCertsInput'] +export type OrganizationFielInput = Input['schemas']['OrganizationFielInput'] +export type OrganizationLogoInput = Input['schemas']['OrganizationLogoInput'] +export type OrganizationCustomizationInput = + Input['schemas']['OrganizationCustomizationInput'] +export type OrganizationReceiptsInput = + Input['schemas']['OrganizationReceiptsInput'] +export type OrganizationSelfInvoiceInput = + Input['schemas']['OrganizationSelfInvoiceInput'] +export type DomainField = Output['schemas']['DomainField'] +export type OrganizationDomainInput = + Input['schemas']['OrganizationDomainInput'] +export type OrganizationSeriesCreateInput = + Input['schemas']['OrganizationSeriesCreateInput'] +export type OrganizationSeriesUpdateInput = + Input['schemas']['OrganizationSeriesUpdateInput'] +export type OrganizationSeriesDefaultInput = + Input['schemas']['OrganizationSeriesDefaultInput'] +export type OrganizationSeriesGroup = + Output['schemas']['OrganizationSeriesGroup'] +export type OkResponse = Output['schemas']['OkResponse'] +export type OrganizationInviteList = Output['schemas']['OrganizationInviteList'] +export type OrganizationPermissionRole = + Output['schemas']['OrganizationPermissionRole'] +export type OrganizationPermissionRoleList = + Output['schemas']['OrganizationPermissionRoleList'] +export type OrganizationPermissionRoleTemplate = + Output['schemas']['OrganizationPermissionRoleTemplate'] +export type OrganizationPermissionRoleTemplateList = + Output['schemas']['OrganizationPermissionRoleTemplateList'] +export type OrganizationPermissionOperationList = + Output['schemas']['OrganizationPermissionOperationList'] +export type OrganizationUserAccessList = + Output['schemas']['OrganizationUserAccessList'] +export type OrganizationInviteRespondInput = + Input['schemas']['OrganizationInviteRespondInput'] +export type OrganizationPermissionRoleCreateInput = + Input['schemas']['OrganizationPermissionRoleCreateInput'] +export type OrganizationPermissionRoleUpdateInput = + Input['schemas']['OrganizationPermissionRoleUpdateInput'] +export type OrganizationUserAccessRoleUpdateInput = + Input['schemas']['OrganizationUserAccessRoleUpdateInput'] diff --git a/src/generated/output.ts b/src/generated/output.ts new file mode 100644 index 0000000..0ff51f5 --- /dev/null +++ b/src/generated/output.ts @@ -0,0 +1,11097 @@ +// Generated by pnpm generate:sdk. Do not edit directly. +import type { TaxType } from '../enums' +import type { TaxFactor } from '../enums' +import type { BinaryDownload } from '../types/runtime' +import type { IssuingType } from '../enums' +import type { IepsMode } from '../enums' +import type { WebhookEndpointStatus } from '../types/webhook' +import type { InvoiceType } from '../enums' +import type { InvoiceStatus } from '../enums' +import type { CancellationStatus } from '../enums' +import type { PaymentMethod } from '../enums' +import type { GlobalInvoicePeriodicity } from '../enums' +import type { ReceiptStatus } from '../enums' +import type { InvoicingPeriod } from '../enums' +export interface paths { + '/catalogs/cartaporte/3.1/air-transport-codes': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar códigos de transporte aéreo + * Devuelve entradas del catálogo de aerolíneas que coinciden con la consulta. Usado para el complemento Carta Porte. + */ + get: operations['searchCartaPorteAirTransportCodes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/comercioexterior/2.0/tariff-fractions': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar fracciones arancelarias + * Devuelve fracciones arancelarias que coinciden con la consulta. + */ + get: operations['searchComercioExteriorTariffFractions'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/transport-configs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar configuraciones de autotransporte + * Devuelve configuraciones de transporte (p. ej., camión/semirremolque). + */ + get: operations['searchCartaPorteTransportConfigs'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/rights-of-passage': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar derechos de paso + * Devuelve derechos de paso ferroviarios que coinciden con la consulta. + */ + get: operations['searchCartaPorteRightsOfPassage'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/customs-documents': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar documentos aduaneros + * Devuelve tipos de documentos aduaneros. + */ + get: operations['searchCartaPorteCustomsDocuments'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/packaging-types': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar tipos de empaque + * Devuelve tipos de empaque para mercancías. + */ + get: operations['searchCartaPortePackagingTypes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/trailer-types': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar tipos de remolque + * Devuelve tipos de remolque/semirremolque. + */ + get: operations['searchCartaPorteTrailerTypes'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/hazardous-materials': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar materiales peligrosos + * Devuelve entradas del catálogo de materiales peligrosos. + */ + get: operations['searchCartaPorteHazardousMaterials'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/naval-authorizations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar autorizaciones navales + * Devuelve códigos de autorización naval (solo `key`). + */ + get: operations['searchCartaPorteNavalAuthorizations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/port-stations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar estaciones/puertos + * Devuelve entradas de estaciones aéreas/marítimas/terrestres. + */ + get: operations['searchCartaPortePortStations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/cartaporte/3.1/marine-containers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Buscar contenedores marítimos + * Devuelve tipos de contenedores marítimos. + */ + get: operations['searchCartaPorteMarineContainers'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar clientes + * Regresa una lista paginada de todos los clientes de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listCustomers'] + put?: never + /** + * Crear cliente + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + */ + post: operations['createCustomer'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener cliente por ID + * Regresa el objeto 'Customer' relacionado al `id` especificado. + */ + get: operations['getCustomer'] + /** + * Editar cliente + * Actualiza la información de un cliente existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + */ + put: operations['editCustomer'] + post?: never + /** + * Eliminar cliente + * Elimina el cliente de tu organización. Las facturas asociadas al cliente **no** se eliminarán. + */ + delete: operations['deleteCustomer'] + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}/email-edit-link': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar enlace de edición por correo electrónico + * Envía un enlace para que el cliente pueda editar su información fiscal. + * + * Este enlace estará disponible en el campo `edit_link`, será válido por 3 días y sólo se podrá usar una vez. + */ + post: operations['sendEditLinkByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/customers/{customer_id}/tax-info-validation': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Validar información fiscal + * Valida que la información fiscal del cliente coincida con los registros del SAT. + * + * Su función principal es validar que los datos del cliente registrado siguen cumpliendo la validación del SAT. + * + * :::tip + * Las operaciones de crear cliente, editar cliente y crear factura ya realizan una + * validación de la información del cliente, por lo que **no** es necesario llamar a este endpoint + * antes de realizar dichas operaciones. + * ::: + */ + get: operations['validateCustomerTaxInfo'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/products': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar productos + * Regresa una lista paginada de todos los productos de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listProducts'] + put?: never + /** + * Crear producto + * Registra un nuevo producto o servicio en tu catálogo de Facturapi. + * + * Puedes usar el ID del producto para crear facturas sin tener que enviar todos los datos del producto cada vez. + * + * Ten en cuenta que los productos que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + */ + post: operations['createProduct'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/products/{product_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener producto por ID + * Regresa el objeto `Product` relacionado al `id` especificado. + */ + get: operations['getProduct'] + /** + * Editar producto + * Actualiza la información de un producto existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + */ + put: operations['editProduct'] + post?: never + /** + * Eliminar producto + * Elimina el producto de tu organización. Las facturas asociadas al producto **no** se eliminarán. + */ + delete: operations['deleteProduct'] + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar facturas + * Regresa una lista paginada de todas las facturas de una organización o realiza una búsqueda de acuerdo a parámetros. + * + * Por defecto, los resultados se ordenan por fecha de emisión, usando el campo `date` de forma descendente. + */ + get: operations['listInvoices'] + put?: never + /** + * Crear factura (CFDI 4.0) + * Crea una nueva Factura. Si la factura es creada en ambiente Live, ésta será **timbrada y enviada al SAT**. + * + * Revisa e infórmate sobre el [rescate de CFDI en intermitencias (Status 202)](/docs/guides/invoices/intermitencias). + */ + post: operations['createInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener factura por ID + * Regresa el objeto 'Invoice' relacionado al `id` especificado. + */ + get: operations['getInvoice'] + /** + * Editar borrador de factura + * Actualiza la información de una factura con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * En el objeto `invoice` de respuesta, Facturapi asignará automáticamente + * el campo `is_ready_to_stamp` con el valor `true` si la factura pasa la + * validación mínima requerida para ser timbrada; de lo contrario, el campo + * `is_ready_to_stamp` será `false`. + */ + put: operations['updateDraftInvoice'] + post?: never + /** + * Cancelar factura + * Realiza una solicitud de cancelación de factura ante el SAT, soportando el esquema de cancelación 2022. + * + * Al usar este método pueden ocurrir 3 posibles resultados: + * + * - Que la llamada regrese un error con la explicación de por qué no se pudo cancelar. + * - Que la llamada sea satisfactoria y regrese un objeto `invoice` con la propiedad `status: "canceled"`. + * - Que la llamada sea satisfactoria, pero que la cancelación requiera de confirmación de parte de tu cliente, en cuyo caso se obtendrá como respuesta el objeto `invoice` con las propiedades `status: "valid"` y `cancellation_status: "pending"`. + * + * En el tercer escenario, el valor de `cancellation_status` será actualizado automáticamente por Facturapi cuando tu cliente acepte, rechace o deje expirar la solicitud, de tal manera que al consultar una factura (usando [Obtener Factura](#tag/invoice/operation/getInvoice)), la propiedad `cancellation_status` reflejará el estado más reciente de la solicitud. + * + * Consulta los valores posibles de `cancellation_status` más abajo. + * + * Después de la cancelación la factura ya no tendrá validez, el objeto cambiará su `status` a `"canceled"` y seguirá estando disponible para futuras consultas. + * + * Si el status de la factura es `draft`, este método la eliminará de la base de datos. + * + * Si el status de la factura es `canceled`, este método regresará un error. + */ + delete: operations['cancelInvoice'] + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/copy': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Copiar a borrador + * Crea una copia en borrador de la factura especificada. + */ + post: operations['copyToDraftInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/stamp': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Timbrar borrador de factura + * Timbra una factura con status `draft` y la envía al SAT para su validación. + * + * Al usar este método, el valor del campo `is_ready_to_stamp` (asignado por Facturapi) + * deberá ser `true`. De otra forma, la llamada regresará un error. + * + * Este método no permite editar la factura, sólo timbrarla. Si necesitas editar información + * en la factura antes de timbrarla, usa el método [Editar Borrador de Factura](#tag/invoice/operation/editDraftInvoice). + */ + post: operations['stampDraftInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/status': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Actualizar status de factura + * Consulta el status de una factura timbrada en el SAT y actualiza el objeto invoice + * con La información más reciente. + */ + put: operations['updateInvoiceStatus'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/payment-summary': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Resumen de pago + * Devuelve la información necesaria para agregar esta factura como documento relacionado en un + * Comprobante de Pago (complemento de pago): el número de parcialidad que corresponde según el + * historial de pagos, el saldo anterior (`last_balance`) y el desglose de impuestos de la factura + * prorrateado al monto que se pretende pagar. + * + * El valor de retorno está listo para usarse como elemento de `related_documents` al + * [crear una factura de tipo Pago](#tag/invoice/operation/createInvoice). + * + * El parámetro `amount` debe expresarse en la divisa de la factura y no puede exceder el saldo + * pendiente (`amount_due`). Cuando el pago se recibe en otra divisa, convierte el monto antes de + * llamar este método. + */ + get: operations['getInvoicePaymentSummary'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/preview/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Vista previa de factura en PDF + * Genera una vista previa en PDF de una factura sin timbrar ni guardar en la organización. + */ + post: operations['previewInvoicePdf'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/preview/pdf/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Obtener URL del preview PDF de factura + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura sin timbrar. + */ + post: operations['previewInvoicePdfUrl'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar factura + * Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + */ + get: operations['downloadInvoice'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la factura en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getInvoiceDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/cancellation_receipt/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar acuse de cancelación + * Descarga en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + */ + get: operations['downloadCancellationReceiptXml'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/cancellation_receipt/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace del acuse de cancelación + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getCancellationReceiptDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/{invoice_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar factura por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + */ + post: operations['sendInvoiceByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar solicitudes de ZIP mensual + * Regresa una lista paginada de solicitudes de ZIP. `year` y `month` deben enviarse juntos. `invoice_types` filtra por un tipo o por un arreglo normalizado exacto. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['listInvoiceZipRequests'] + put?: never + /** + * Crear o recuperar solicitud de ZIP mensual + * Crea una solicitud para generar un archivo ZIP con las facturas de un mes, o recupera la solicitud existente con los mismos filtros. + * + * La operación es idempotente. Los tipos de factura se normalizan, por lo que `["I", "E"]` y `["E", "I"]` corresponden a la misma solicitud. Las llamadas concurrentes idénticas también regresan la misma solicitud. + * + * Si una solicitud anterior tiene status `failed`, volver a llamar este método reintentará su procesamiento. Antes del nuevo intento se limpian el error, la tarea anterior, el progreso procesado y la lista de documentos fallidos. Si no es posible programar la generación, la solicitud se guarda con status `failed` y la API regresa un error `5xx`. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. Las llaves de ambiente Test regresan HTTP 402. + */ + post: operations['createInvoiceZipRequest'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Recuperar solicitud de ZIP mensual + * Recupera una solicitud de ZIP. Consulta este método hasta que el status sea `finished` o `failed`. Cuando sea `finished`, descarga el archivo con el método de descarga. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['retrieveInvoiceZipRequest'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}/zip': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar ZIP mensual + * Descarga el ZIP de una solicitud terminada. El nombre del archivo usa el formato `YYYY-MM.zip`. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['downloadInvoiceZipRequest'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/invoices/zip-requests/{id}/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener URL de descarga del ZIP mensual + * Devuelve un objeto con los metadatos del archivo y una URL temporal para descargar el ZIP de una solicitud terminada sin que el archivo viaje a través de tu servidor. + * + * La URL permite acceder únicamente a ese archivo mientras sea válida: trátala como una credencial y no la almacenes. Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + */ + get: operations['getInvoiceZipRequestDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar recibos + * Regresa una lista paginada de todos los recibos de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listReceipts'] + put?: never + /** + * Crear recibo + * Crea un nuevo Recibo, el cual funge como nota de venta. + * + * Todos los recibos generan una URL de autofactura que cliente puede + * visitar para llenar sus datos fiscales en un micrositio con el branding + * de la organización. + */ + post: operations['createReceipt'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener recibo por ID + * Regresa el objeto 'Receipt' relacionado al `id` especificado. + */ + get: operations['getReceipt'] + /** + * Asignar o reasignar cliente a recibo + * Asigna o reasigna un cliente existente (por ID) a un recibo, o crea uno nuevo enviando el objeto del cliente. + */ + put: operations['assignReceiptCustomer'] + post?: never + /** + * Cancelar recibo + * Marca un recibo como cancelado, cambiando su propiedad `status` a `"canceled"`. + * + * Una vez cancelado, el recibo no podrá ser facturado. + */ + delete: operations['cancelReceipt'] + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Facturar recibo + * Crea una factura a partir de un recibo. + * + * Sólo pueden facturarse recibos abiertos (`status = "open"`) + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado al recibo. Si omites `customer`, el + * recibo debe tener un cliente asignado previamente. + * + * Una vez facturado, el `status` del recibo cambiará a `"invoiced_to_customer"`. + */ + post: operations['invoiceReceipt'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Facturar múltiples recibos + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + */ + post: operations['createToInvoiceFromReceipts'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice/preview': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Vista previa PDF de factura múltiple + * Genera una vista previa en PDF para una factura construida a partir de múltiples recibos seleccionados por `key`. + * + * La vista previa valida las mismas reglas de cliente que la creación real: + * si omites `customer`, todos los recibos deben tener asignado el mismo cliente. + */ + post: operations['previewToInvoiceFromReceipts'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/to-invoice/preview/download-url': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Obtener URL del preview de factura de recibos + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura construida con los recibos seleccionados. + */ + post: operations['previewToInvoiceFromReceiptsUrl'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/global-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Crear factura global + * Crea una factura global que incluirá todos los recibos con `status = “open”` de un cierto periodo. + * + * La factura global se emite al cliente genérico `PUBLICO EN GENERAL`. + * Los recibos incluidos quedan asociados a ese cliente y su `status` + * cambia a `"invoiced_globally"`. + * + * Una factura global puede incluir hasta 5,000 recibos abiertos. Si el periodo + * contiene más, puedes enviar `limit_to_max_receipts: true` y repetir la solicitud + * con el mismo periodo hasta recibir `null`. + */ + post: operations['createGlobalInvoice'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar PDF + * Descarga el recibo digital en formato PDF. + */ + get: operations['downloadReceiptPdf'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/download-url/pdf': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar el recibo digital en PDF, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getReceiptDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/receipts/{receipt_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar recibo por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente. + * + * El correo enviado estará personalizado con el logotipo y los colores de la organización que lo creó, + * e incluirá un botón para facturar el recibo, así con el recibo en formato PDF adjunto al mensaje. + */ + post: operations['sendReceiptByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar retenciones + * Regresa una lista paginada de todas las retenciones de una organización o realiza una búsqueda de acuerdo a parámetros + */ + get: operations['listRetentions'] + put?: never + /** + * Crear retención + * Crea una nueva Retención. Si el comprobante es creado en ambiente Live, ésta será **timbrado y enviado al SAT**. + * + * Para crear una retención en borrador, envía `status: "draft"`. En ese caso, + * la retención se guardará sin timbrarse, no se enviará al PAC y podrá estar + * incompleta. Facturapi asignará `is_ready_to_stamp: true` únicamente cuando + * el borrador tenga todos los datos requeridos para timbrarse. + */ + post: operations['createRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener retención por ID + * Regresa el objeto 'Retention' relacionado al `id` especificado. + */ + get: operations['getRetention'] + /** + * Editar borrador de retención + * Actualiza la información de una retención con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * Facturapi recalculará automáticamente `is_ready_to_stamp` después de cada + * edición. Si la retención ya no está en status `draft`, la llamada regresará + * un error. + */ + put: operations['updateDraftRetention'] + post?: never + /** + * Cancelar retención + * Realiza una solicitud de cancelación de retención ante el SAT. + * + * A diferencia de las facturas comunes, la cancelación de la retención es inmediata y no requiere autorización de parte del receptor. + * + * Si el status de la retención es `draft`, este método la eliminará de la + * base de datos sin llamar al SAT/PAC y sin requerir parámetros de cancelación. + */ + delete: operations['cancelRetention'] + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/copy': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Copiar a borrador + * Crea una copia en borrador de la retención especificada. La copia no conserva + * campos propios del timbrado, cancelación, idempotencia o identidad externa. + */ + post: operations['copyToDraftRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/stamp': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Timbrar borrador de retención + * Timbra una retención con status `draft` y la envía al SAT para su validación. + * + * Facturapi validará el borrador como una retención completa antes de timbrarlo. + * Si el borrador está incompleto o no es válido, la llamada regresará un error. + */ + post: operations['stampDraftRetention'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Descargar retención + * Descarga una retención en PDF, XML o ambos en un archivo comprimido ZIP. + */ + get: operations['downloadRetention'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/download-url/{format}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener enlace de descarga + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la retención en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + */ + get: operations['getRetentionDownloadUrl'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/retentions/{retention_id}/email': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Enviar retención por correo electrónico + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + */ + post: operations['sendRetentionByEmail'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar organizaciones + * Regresa una lista paginada de todas las organizationes registradas bajo tu cuenta, o realiza una búsqueda de acuerdo a parámetros. + */ + get: operations['listOrganizations'] + put?: never + /** + * Crear organización + * Crea una nueva Organización que pertenecerá a tu cuenta de usuario. + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](#tag/organization/operation/uploadOrganizationCertificate) + * + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](#tag/organization/operation/uploadOrganizationCertificate), + * además de firmar la Carta Manifiesto que autoriza a nuestro PAC a timbrar facturas; + * puedes hacerlo en [tu dashboard](https://dashboard.facturapi.io/settings/manifiesto) + * o en [nuestro portal público](https://www.facturapi.io/manifiesto). También puedes incrustar + * en tu solución el módulo de firma de la carta (sin logos, listo para iframe): https://www.facturapi.io/embedded/manifiesto + * + * Recuerda que los folios de tu suscripción podrán ser consumidos por + * cualquiera de las organizaciones registradas bajo tu cuenta. + */ + post: operations['createOrganization'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/me': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Detalle de organización + * Retorna el detalle de la organización actualmente autenticada. + */ + get: operations['meOrganization'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener organización por ID + * Regresa el objeto 'Organization' relacionado al `id` especificado. + */ + get: operations['getOrganization'] + put?: never + post?: never + /** + * Eliminar organización + * Elimina la organización de tu cuenta de Facturapi. Una vez eliminada, + * ya no podrás acceder a sus recursos, tales como clientes, productos, + * facturas, recibos o retenciones. + */ + delete: operations['deleteOrganization'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/legal': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar datos fiscales + * Actualiza los datos fiscales de la organización. + * + * Si estás buscando cómo editar el RFC, recuerda que la propiedad + * `tax_id` se asigna automáticamente al subir los Certificados de Sello + * Digital. + */ + put: operations['editOrganizationLegal'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/certificate': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir certificados (CSD) + * Sube los archivos del Certificado de Sello Digital (CSD) proporcionado + * por el SAT. Esta llamada también debe usarse para reemplazar los + * certificados existentes en caso de solicitar nuevos. + * + * Al actualizar tus certificados se leerá el RFC y asignará + * automáticamente a `legal.tax_id`. + */ + put: operations['uploadOrganizationCertificate'] + post?: never + /** + * Eliminar certificados (CSD) + * Elimina los certificados (CSD) de tu organización. + * + * Esto no afecta a las facturas ya emitidas, pero no podrás emitir nuevas facturas hasta que subas nuevos certificados. + */ + delete: operations['deleteOrganizationCertificate'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/fiel': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir certificado FIEL + * Sube los archivos de la e.firma (FIEL) de la organización. + * + * La e.firma (FIEL) no es necesaria para crear CFDI. Para timbrar CFDI + * solo necesitas cargar el Certificado de Sello Digital (CSD). La FIEL es + * necesaria para utilizar la descarga masiva de CFDI. + */ + put: operations['uploadOrganizationFiel'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/logo': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Subir logotipo + * Sube el logotipo de la organización que será colocado en el PDF y en + * los correos que se envían al cliente con la factura adjunta. + * + * El archivo debe ser una imagen en formato JPG o PNG y tener un tamaño + * no mayor a 500 KB. Las dimensiones recomendadas son 800 × 500px. + * + * Si la organización ya tiene un logotipo, esta llamada reemplaza el + * logotipo anterior. + */ + put: operations['uploadOrganizationLogo'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/customization': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar personalización + * Actualiza la información relacionada con la identidad o branding de la organización. + */ + put: operations['editOrganizationCustomization'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/receipts': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar config. recibos + * Actualiza los campos enviados de la configuración de recibos de la organización. + * Para activar la generación automática de facturas globales, la organización + * debe tener contratado ese feature. + */ + put: operations['editOrganizationReceiptsSettings'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/self-invoice': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar config. autofactura + * Actualiza la configuración del portal de autofactura de la organización. + */ + put: operations['editOrganizationSelfInvoiceSettings'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/domain-check': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Revisar dominio disponible + * Revisa si un identificador está disponible para elegir como dominio para el portal de autofactura. + */ + get: operations['checkDomainAvailability'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/domain': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Elegir dominio de autofactura + * Elige el dominio que utilizará esta organización en su micrositio de + * autofactura. Una vez elegido el dominio, deberás ponerte en contacto + * con nosotros si necesitas cambiarlo. + * + * El dominio que elijas será el que aparecerá en el campo + * `self_invoice_url` al crear un nuevo recibo, de la siguiente manera: + * + * `https://factura.space/{DOMAIN}/{RECEIPT_KEY}` + */ + put: operations['editOrganizationDomain'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/test': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener Test Api Key + * Obtiene la llave secreta de ambiente Test de la organización. + */ + get: operations['getTestApiKey'] + /** + * Renovar Test API Key + * Renueva la llave secreta de ambiente Test de la organización e invalida inmediatamente la anterior. + */ + put: operations['renewTestApiKey'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/live': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar Live API Keys + * Listar llaves secretas de ambiente Live de la organización. + */ + get: operations['listLiveApiKeys'] + /** + * Crear Live API Key + * Genera una nueva llave secreta de ambiente Live de la organización. + * Esta operación no invalida las llaves generadas previamente. El endpoint usa `PUT` + * por compatibilidad histórica, pero su comportamiento es crear una nueva llave. + */ + put: operations['renewLiveApiKey'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/apikeys/live/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Revocar Live API Key + * Revocar Live Api Key de tu organización. + */ + delete: operations['deleteLiveApiKey'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listado de series + * Listado de series creadas para la personalización de organización. La cual lleva control de foliaje para cada tipo de factura si está asignada en las personalización de organización. + */ + get: operations['getSeriesGroup'] + put?: never + /** + * Crear serie + * Crea una nueva serie de folios para la organización. + * Las series son útiles para llevar un control de los folios emitidos para cada tipo de factura. + */ + post: operations['createSeriesGroup'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group/default-series': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Establecer serie predeterminada + * Asigna una serie predeterminada para el tipo de comprobante indicado. + */ + put: operations['updateDefaultSeries'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/series-group/{series_name}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** + * Editar serie + * Edita el número de foliaje de la serie en ambientes Test y Live de la organización. + */ + put: operations['updateSeriesGroup'] + post?: never + /** + * Eliminar serie + * Elimina la serie previamente creada + */ + delete: operations['deleteSeriesGroup'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar usuarios con acceso a organización + * Regresa un arreglo con los usuarios que actualmente tienen acceso a la organización, incluyendo al propietario. Este endpoint no está paginado. + */ + get: operations['getOrganizationTeam'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/invites': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar invitaciones enviadas + * Regresa invitaciones enviadas desde la organización. + */ + get: operations['listOrganizationTeamInvites'] + put?: never + /** + * Invitar usuario a organización + * Crea o actualiza una invitación de usuario. Por defecto, el acceso es de administrador con permisos completos; para limitarlo, crea un rol y envía su ID en `role`. + * + * Cada organización puede invitar a un usuario sin costo adicional. A partir del segundo usuario invitado, cada usuario adicional tendrá un costo mensual. Este cargo se aplica automáticamente cuando el usuario acepta la invitación. + * Puedes consultar el precio vigente en nuestra [página de precios](https://www.facturapi.io/pricing). + */ + post: operations['createOrganizationTeamInvite'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/{access_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener acceso de usuario + * Regresa el detalle del acceso del usuario dentro de la organización usando su `access_id`, incluyendo accesos implícitos como el del propietario. + */ + get: operations['getOrganizationTeamUser'] + put?: never + post?: never + /** Eliminar usuario con acceso */ + delete: operations['removeOrganizationUserAccess'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/invites/{invite_key}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Cancelar invitación enviada + * Elimina una invitación pendiente de la organización. + */ + delete: operations['deleteOrganizationTeamInvite'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/invites/pending': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar invitaciones recibidas + * Regresa las invitaciones recibidas para el usuario autenticado. + */ + get: operations['listPendingOrganizationInvites'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/invites/{invite_key}/response': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Responder invitación + * Acepta o rechaza una invitación usando su `invite_key`. + */ + post: operations['respondOrganizationInvite'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar roles de organización */ + get: operations['listOrganizationPermissionRoles'] + put?: never + /** Crear rol de organización */ + post: operations['createOrganizationPermissionRole'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/templates': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar plantillas de roles */ + get: operations['listOrganizationPermissionRoleTemplates'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/operations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Listar operaciones de permisos */ + get: operations['listOrganizationPermissionOperations'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/roles/{role_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Obtener rol de organización */ + get: operations['getOrganizationPermissionRole'] + /** Actualizar rol de organización */ + put: operations['updateOrganizationPermissionRole'] + post?: never + /** Eliminar rol de organización */ + delete: operations['deleteOrganizationPermissionRole'] + options?: never + head?: never + patch?: never + trace?: never + } + '/organizations/{organization_id}/team/{access_id}/role': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** Reasignar rol a usuario */ + put: operations['updateOrganizationTeamUserRole'] + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Listar webhooks + * Retorna una lista de webhooks creados previamente para la organización. + */ + get: operations['listWebhooks'] + put?: never + /** + * Crear Webhook + * Registra un nuevo webhook en tu organización de Facturapi. + * Utiliza esta llamada para recibir notificaciones de eventos asíncronos a la API. + * Los webhooks de ambiente test y ambiente live son independientes. + */ + post: operations['createWebhook'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks/{webhook_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Obtener webhook por ID + * Regresa el objeto "Webhook" relacionado al `id` especificado. + */ + get: operations['getWebhook'] + /** + * Editar webhook + * Actualiza la información de un Webhook existente con los parámetros que envíes en la petición. + */ + put: operations['editWebhook'] + post?: never + /** + * Eliminar Webhook + * Elimina el webhook perteneciente a la organización. + */ + delete: operations['deleteWebhook'] + options?: never + head?: never + patch?: never + trace?: never + } + '/webhooks/validate-signature': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Validar evento de webhook + * Valida la firma de un evento recibido mediante un Webhook. + * Utiliza esta operación para verificar la autenticidad e integridad de + * un evento recibido, comparando la firma recibida con la generada por Facturapi. + */ + post: operations['validateWebhookSignature'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/check': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Health check (Pulso) + * Comprueba que la API está disponible. Este endpoint requiere una llave secreta de API. + */ + get: operations['checkApiHealth'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/tools/tax_id_validation': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Validar RFC + * Consulta el estado de un RFC en la lista de **EFOS** (Empresas que + * Facturan Operaciones Simuladas). Al aparecer en esta lista, el RFC es o + * fue sospechoso de incurrir en simulación de operaciones fiscales + * (empresas factureras). + * + * La respuesta (detallada más abajo) incluye los resultados de esta + * validación. Se incluye la propiedad + * booleana `is_valid`, que Facturapi resuelve interpretando la respuesta. + * Un valor de `true` para esta propiedad indica que el RFC no tiene asuntos + * por resolver y está libre de problemas; y lo contrario para `false`. + * + * Adicionalmente puedes consultar la propiedad data para ver los valores + * en bruto de la consulta al SAT. + */ + get: operations['validateTaxId'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/products': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Clave Producto/Servicio + * Busca en el catálogo Productos/Servicios del SAT, el cual contiene la clave a incluir en la factura. + */ + get: operations['searchProducts'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/catalogs/units': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Unidades de medida + * Busca en el catálogo de Unidades de Medida del SAT. + */ + get: operations['searchUnits'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export interface webhooks { + 'invoice.global_invoice_created': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Factura global creada + * Notifica acerca de la creación de una factura global a partir de e-Receipts. + */ + post: operations['onInvoiceGlobalInvoiceCreated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de factura actualizado + * Notifica acerca del cambio del campo `status` de una factura. + * + * Se utiliza cuando la factura se crea de manera asíncrona o cuando una tarea de recuperación por intermitencia de timbrado cambia su estado. + */ + post: operations['onInvoiceStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.created_from_dashboard': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Creación de factura desde dashboard + * Notifica cuandos se crea una factura desde dashboard de Facturapi. + */ + post: operations['onInvoiceCreatedFromDashboard'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'invoice.cancellation_status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de cancelación actualizado + * Notifica acerca de cambios en el campo `cancellation_status` de una factura. + */ + post: operations['onInvoiceCancellationStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'receipt.self_invoice_complete': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Autofactura completada + * Notifica acerca de la creación de una autofactura a partir de un e-Receipt. + */ + post: operations['onReceiptSelfInvoiceComplete'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'receipt.status_updated': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Estatus de recibo actualizado + * Notifica acerca de cambios en el campo `status` de un recibo. + */ + post: operations['onReceiptStatusUpdated'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + 'customer.edit_link_completed': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Edición de cliente completada */ + post: operations['onCustomerEditLinkCompleted'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export interface components { + schemas: { + /** Fecha en formato YYYY-MM-DD o fecha y hora en formato ISO8601. */ + DateOrDateTime: string | Date + InvoiceGlobalInvoiceCreatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.global_invoice_created' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.global_invoice_created' + } + InvoiceStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.status_updated' + } + InvoiceCreatedFromDashboardEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.created_from_dashboard' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.created_from_dashboard' + } + InvoiceCancellationStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'invoice.cancellation_status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'invoice' + object: components['schemas']['Invoice'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'invoice.cancellation_status_updated' + } + ReceiptSelfInvoiceCompleteEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'receipt.self_invoice_complete' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'receipt' + object: components['schemas']['Receipt'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'receipt.self_invoice_complete' + } + ReceiptStatusUpdatedEvent: components['schemas']['EventBase'] & { + /** + * Tipo de evento + * @enum {string} + */ + type: 'receipt.status_updated' + data: { + /** + * Tipo de objeto asociado al evento + * @enum {string} + */ + type: 'receipt' + object: components['schemas']['Receipt'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'receipt.status_updated' + } + CustomerEditLinkCompletedEvent: components['schemas']['EventBase'] & { + /** @enum {string} */ + type: 'customer.edit_link_completed' + data: { + /** @enum {string} */ + type: 'customer' + object: components['schemas']['Customer'] + } + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'customer.edit_link_completed' + } + ApiEvent: + | components['schemas']['InvoiceGlobalInvoiceCreatedEvent'] + | components['schemas']['InvoiceStatusUpdatedEvent'] + | components['schemas']['InvoiceCreatedFromDashboardEvent'] + | components['schemas']['InvoiceCancellationStatusUpdatedEvent'] + | components['schemas']['ReceiptSelfInvoiceCompleteEvent'] + | components['schemas']['ReceiptStatusUpdatedEvent'] + | components['schemas']['CustomerEditLinkCompletedEvent'] + /** Objeto con un enlace temporal de descarga y los metadatos del archivo. */ + SignedDownloadUrl: { + /** + * Format: uri + * Enlace de descarga. Da acceso al archivo mientras siga vigente. + */ + url: string + /** + * Format: date-time + * Momento en el que el enlace deja de funcionar. + */ + expires_at: Date + /** Tipo de contenido del archivo. */ + content_type: string + /** Nombre sugerido del archivo. */ + filename: string + } + SearchKeyDescriptionResult: components['schemas']['SearchResult'] & { + data?: { + /** Clave del catálogo */ + key?: string + /** Descripción de la entrada del catálogo */ + description?: string + }[] + } + RelatedResourceMessage: { + /** Tipo de recurso relacionado. */ + resource_type?: string + /** ID del recurso relacionado. */ + resource_id?: string + /** Origen del mensaje. */ + source?: string + /** + * Severidad del mensaje. + * @enum {string} + */ + severity?: 'error' | 'warning' | 'info' + /** Mensaje relacionado con el recurso. */ + message?: string + /** + * Format: date-time + * Fecha y hora de creación del mensaje. + */ + created_at?: Date + } + EventBase: { + /** ID del evento */ + id: string + /** + * Format: date-time + * Fecha y hora de creación del evento + */ + created_at: Date + /** Indica si el evento se generó en modo test (false) o en modo producción (true). */ + livemode: boolean + /** ID de la organización a la que pertenece el evento */ + organization: string + /** Mensajes relacionados con el recurso asociado al evento. */ + related_resource_messages?: components['schemas']['RelatedResourceMessage'][] + } + DateRange: { + /** + * Greater than + * Format: date-time + * Límite inferior exclusivo del rango de fechas a solicitar. + */ + gt?: Date + /** + * Greater than or equals + * Format: date-time + * Límite inferior inclusivo del rango de fechas a solicitar. + */ + gte?: Date + /** + * Lesser than + * Format: date-time + * Límite superior exclusivo del rango de fechas a solicitar. + */ + lt?: Date + /** + * Lesser than or equals + * Format: date-time + * Límite superior inclusivo del rango de fechas a solicitar. + */ + lte?: Date + } + GenericError: { + /** + * Descripción del error + * Indica qué salió mal y puede incluir una sugerencia sobre cómo solucionar el error. + */ + message: string + /** + * Código de estado HTTP + * Format: int32 + * Código de estado HTTP de esta respuesta de error. + */ + status: number + /** Indica si la petición fue exitosa. Siempre `false` en respuestas de error. */ + ok: boolean + /** Código de error estable para manejar el error de forma programática. Consulta la guía de manejo de errores para ver la lista de códigos documentados. */ + code: string + /** + * Ubicación opcional del dato relacionado con el error. + * @enum {string} + */ + location?: 'body' | 'query' | 'params' | 'headers' | 'files' + /** Ruta opcional del campo relacionado con el error. */ + path?: string + /** Detalles adicionales del error. Sólo se incluye cuando aporta información útil. */ + errors?: components['schemas']['ErrorDetail'][] + } + ErrorDetail: { + /** Mensaje legible del detalle. */ + message: string + /** Subcódigo del detalle. En validaciones de Facturapi usa códigos como `required`, `invalid_type` o `tax_id_not_found`; en errores externos puede contener el código original del proveedor. */ + code: string + /** + * Ubicación opcional del dato relacionado con este detalle. + * @enum {string} + */ + location?: 'body' | 'query' | 'params' | 'headers' | 'files' + /** Ruta opcional del campo relacionado con este detalle. */ + path?: string + /** + * Fuente del detalle. + * @enum {string} + */ + source: 'facturapi' | 'sat' | 'pac' + } + /** + * Indica si la factura fue emitida por tu organización o recibida de un tercero. + * @enum {string} + */ + IssuingType: IssuingType + /** + * Estado de la solicitud de cancelación de la factura. + * @enum {string} + */ + CancellationStatus: 'none' | 'accepted' | 'pending' | 'rejected' | 'expired' + SearchResult: { + /** + * Página + * Número de página. Vale 0 cuando no hay coincidencias. Se omite en todas las respuestas de paginación por cursor, incluida la primera página. + */ + page?: number + /** + * Páginas totales + * Total de páginas. Se omite en todas las respuestas de paginación por cursor, incluida la primera página. + */ + total_pages?: number + /** + * Resultados totales + * Número de elementos individuales en todas las páginas de resultados. En modo `pagination=cursor` solo se incluye en la primera página de la búsqueda (sin `after`/`before`); el total no cambia entre páginas. + */ + total_results?: number + /** + * Cursor anterior + * Cursor para obtener la página anterior de resultados. Es `null` en la primera página. Solo disponible con `pagination=cursor`. + */ + previous_cursor?: string | null + /** + * Cursor siguiente + * Cursor para obtener la página siguiente de resultados. Es `null` cuando no hay más resultados. Solo disponible con `pagination=cursor`. + */ + next_cursor?: string | null + /** + * Resultados con tope + * Indica si `total_results` está limitado a 3,000 porque existen más resultados de los reportados. + */ + totals_are_capped?: boolean + } + ResourceAutoGeneratedProps: { + /** ID del objeto */ + id: string + /** + * Format: date-time + * Fecha de registro + */ + created_at: Date + /** Si el valor es `true`, indica que el objeto fue creado en ambiente Live; o si es `false`, en ambiente Test. */ + livemode: boolean + } + TaxIdValidationResult: { + /** + * Resultado de la validación en la lista de Empresas que + * Facturan Operaciones Simuladas del SAT. + */ + efos?: { + /** + * Indica si el RFC tiene algún asunto relacionado con esta lista. + * `true`: El RFC no está en la lista de EFOS o su situación fue + * apelada y resultó favorable. `false`: El RFC está registrado como + * “Presunto” o “Definitivo” en la lista de EFOS. + */ + is_valid?: boolean + /** + * Objeto con el resultado de la búqueda ante el SAT. + * Toda la información contenida en este objeto proviene del SAT. + */ + data?: { + /** + * Disponible sólo cuando el RFC no fue encontrado en la lista, + * lo cual es bueno. + */ + mensaje?: string + /** Texto que indica la fecha de actualización de la lista. */ + fechaLista?: string + /** Arreglo con los resultados de la búsqueda en la lista de EFOS. */ + detalles?: { + /** El RFC consultado, a manera de confirmación. */ + rfc?: string + /** Razón social del contribuyente. */ + razonSocial?: string + /** + * Texto que indica la situación actual. Consulta + * [esta tabla](#situación-del-contribuyente) para ver + * el detalle de los distintos valores. + */ + situacionContribuyente?: string + /** Texto con identificador y fecha del reporte de presunción. */ + numFechaPresuncion?: string + /** + * Format: DD/MM/YYYY + * Fecha de publicación de presunción. + */ + pubFechaSatPresuntos?: string + /** Texto con identificador y fecha de publicación en el listado global de presunción. */ + numGlobalPresuncion?: string + /** + * Format: DD/MM/YYYY + * Fecha de publicación en el Diario Oficial de la Federación (DOF). + */ + pubFechaDofPresuntos?: string + /** Identificador de la publicación de estado “Definitivo”. */ + pubSatDefinitivos?: string + /** + * Format: DD/MM/YYYY + * Fecha de la publicación de estado “Definitivo” en el DOF. + */ + pubDofDefinitivos?: string + /** Texto con identificador y fecha de sentencia favorable. */ + numFechaSentFav?: string + /** + * Format: DD/MM/YYYY + * Fecha de sentencia favorable + */ + pubSatSentFav?: string + }[] + } + } + } + ProductCatalogResult: { + /** Clave del catálogo */ + key?: string + /** Descripción */ + description?: string + /** + * Número del 0 al 1 que representa el nivel de coincidencia del + * resultado con respecto a la consulta de búsqueda. + */ + score?: number + } + UnitCatalogResult: { + /** Clave del catálogo */ + key?: string + /** Descripción */ + description?: string + /** + * Número del 0 al 1 que representa el nivel de coincidencia del + * resultado con respecto a la consulta de búsqueda. + */ + score?: number + } + ProductCatalogSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['ProductCatalogResult'][] + } + UnitCatalogSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['UnitCatalogResult'][] + } + LocalTax: { + /** Tasa del impuesto en fracción decimal. */ + rate: number + /** Base del impuesto. Si se omite, se utiliza el subtotal completo del concepto. */ + base?: number + /** Nombre del impuesto. Texto libre. */ + type: string + /** + * Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + * @default false + */ + withholding?: boolean + /** @enum {string} */ + factor?: TaxFactor + } + /** Tax */ + BaseTax: { + /** Tasa del impuesto en fracción decimal. */ + rate: number + /** Base del impuesto. Si se omite, se calcula a partir del subtotal del concepto y el factor del impuesto. Para el factor Cuota, se utiliza la cantidad de unidades. */ + base?: number + /** + * Tipo de impuesto. + * @default IVA + * @enum {string} + */ + type?: TaxType + ieps_mode?: components['schemas']['IepsMode'] + /** + * Tipo factor + * @default Tasa + * @enum {string} + */ + factor?: TaxFactor + /** + * Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + * @default false + */ + withholding?: boolean + } + /** + * Indica la manera de cobrar el impuesto, y puede tener los valores: + * + * `"sum_before_taxes"`: Aplica primero el IEPS al subtotal y usa el resultado como base del resto de impuestos en el producto. + * + * `"break_down"`: Cobra y desglosa el IEPS al mismo nivel que el resto de los impuestos en el producto. + * + * `"unit"`: Aplica el IEPS antes del precio unitario, y usa el precio unitario original como base para el resto de impuestos. + * + * `"subtract_before_break_down"`: Aplica el IEPS solo para calcular impuestos como IVA de traslado y retenciones, y usa el precio unitario original como base para el resto de impuestos. + * + * Consulta con tu contador qué caso aplica para tu giro de empresa y producto. + * @default sum_before_taxes + * @enum {string} + */ + IepsMode: IepsMode + IepsTax: Omit & { + /** @constant */ + type: 'IEPS' + ieps_mode?: components['schemas']['IepsMode'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'IEPS' + } + /** Información sobre el timbre fiscal digital agregado por el PAC. */ + Stamp: { + /** Sello digital del comprobante fiscal. */ + signature?: string + /** FechaTimbrado del SAT: fecha y hora local sin offset de zona horaria. Se conserva como texto. */ + date?: string + /** Número de serie del certificado del SAT usado para timbrar. */ + sat_cert_number?: string + /** Sello digital del timbre fiscal digital. */ + sat_signature?: string + } + LineItem: { + /** Cuentas prediales de este concepto. */ + property_tax_account?: string[] + /** Cantidad de unidades incluidas del mismo concepto. */ + quantity?: number + /** Monto total de descuento aplicado a este concepto. */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product?: components['schemas']['LineItemProduct'] + /** Objeto con información de las partes de la factura. */ + parts?: components['schemas']['Parts'][] + } + /** + * Objeto con información del contribuyente tercero, a cuenta del que se realiza la operación. + * + * Corresponde al campo "ACuentaTerceros" en el CFDI. + */ + ThirdParty: { + /** Nombre o razón social del tercero. */ + legal_name?: string + /** RFC del tercero. */ + tax_id?: string + /** Régimen fiscal del tercero. */ + tax_system?: string + /** Código postal del tercero. */ + zip?: string + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** + * Monto total de descuento aplicado a este concepto. + * @default 0 + */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemProductInput'] | string + parts?: components['schemas']['PartInput'][] + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** Código XML de tu complemento concepto, el complemento Hidrocarburos y Petrolíferos o el complemento Instituciones Educativas Privadas. */ + complement?: + | string + | components['schemas']['HidroYPetroComplementInput'] + | components['schemas']['IeduComplementInput'] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Números de cuenta para el impuesto predial. */ + property_tax_account?: string[] + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemEgresoInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** + * Monto total de descuento aplicado a este concepto. + * @default 0 + */ + discount?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemProductEgresoInput'] | string + parts?: components['schemas']['PartInput'][] + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** Código XML de tu complemento concepto, el complemento Hidrocarburos y Petrolíferos o el complemento Instituciones Educativas Privadas. */ + complement?: + | string + | components['schemas']['HidroYPetroComplementInput'] + | components['schemas']['IeduComplementInput'] + third_party?: Record & + components['schemas']['ThirdParty'] + } + /** + * LineItem + * Conceptos incluidos en el documento + */ + LineItemTrasladoInput: { + /** + * Cantidad de unidades incluidas del mismo concepto. + * @default 1 + */ + quantity?: number + /** Objeto con información del producto o servicio facturado. */ + product: components['schemas']['LineItemTrasladoProductInput'] | string + /** Números de pedimento asociados a este concepto. */ + customs_keys?: string[] + /** + * Format: xml + * Código XML de tu complemento concepto. + */ + complement?: string + parts?: components['schemas']['PartInput'][] + third_party?: { + /** Nombre o razón social del tercero. */ + legal_name: string + /** RFC del tercero. */ + tax_id: string + /** Régimen fiscal del tercero. */ + tax_system: string + /** Código postal del tercero. */ + zip: string + } + } + /** HidroYPetroComplement */ + HidroYPetroComplementInput: { + /** + * Tipo de permiso otorgado por la autoridad competente, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * @enum {string} + */ + tipo_permiso: + | 'PER01' + | 'PER02' + | 'PER03' + | 'PER04' + | 'PER05' + | 'PER06' + | 'PER07' + | 'PER08' + | 'PER09' + | 'PER10' + | 'PER11' + /** Número de permiso otorgado por la autoridad competente, conforme a la nomenclatura del catálogo c_TipoPermiso. */ + numero_permiso: string + /** + * Subtipo del hidrocarburo o petrolífero, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * @enum {string} + */ + sub_producto_hyp: + | 'SP16' + | 'SP17' + | 'SP18' + | 'SP19' + | 'SP22' + | 'SP23' + | 'SP24' + | 'SP25' + | 'SP48' + /** + * Clave correspondiente a hidrocarburos y petrolíferos, conforme al [Catálogo Hidrocarburos Petrolíferos](#cat%C3%A1logos-hidrocarburos-petrol%C3%ADferos). + * + * Puedes enviarla explícitamente o dejar que Facturapi la derive desde el `product_key` del concepto cuando aplique. + * @enum {string} + */ + clave_hyp?: '15101514' | '15101515' | '15101505' + } + /** + * IeduComplement + * Complemento concepto de Instituciones Educativas Privadas versión 1.0. + * + * Se incluye a nivel concepto dentro de `items[].complement`. + */ + IeduComplementInput: { + /** Nombre del alumno. */ + nombreAlumno: string + /** CURP del alumno de la institución educativa. */ + CURP: string + /** + * Nivel educativo que cursa el alumno. + * @enum {string} + */ + nivelEducativo: + | 'Preescolar' + | 'Primaria' + | 'Secundaria' + | 'Profesional técnico' + | 'Bachillerato o su equivalente' + /** Clave del centro de trabajo o reconocimiento de validez oficial de estudios de la institución educativa privada donde se realiza el pago. */ + autRVOE: string + /** RFC de quien realiza el pago cuando sea diferente a quien recibe el servicio. */ + rfcPago?: string + } + /** + * string + * Format: xml + * Código XML de tu complemento tal cual como quieres que se inserte en el XML. Debe contener solamente un nodo XML raíz. + */ + CustomComplementData: string + /** CustomComplement */ + CustomComplementProperties: { + /** + * Tipo de complemento. (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: 'custom' + data: components['schemas']['CustomComplementData'] + } + /** CustomComplement */ + CustomComplementInput: components['schemas']['CustomComplementProperties'] & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'custom' + } + /** + * NominaComplementData + * Objeto con la información del complemento de nómina. + */ + NominaComplementDataInput: WithRequired< + components['schemas']['NominaComplementDataDirectProperties'], + 'fecha_inicial_pago' | 'fecha_final_pago' | 'num_dias_pagados' + > & + WithRequired< + components['schemas']['NominaComplementDataNestedInput'], + 'receptor' | 'percepciones' + > + /** Complemento de Nómina. */ + NominaComplementDataProperties: components['schemas']['NominaComplementDataDirectProperties'] & + components['schemas']['NominaComplementDataNestedProperties'] + NominaComplementDataDirectProperties: { + /** + * Tipo de nómina. + * - `“O”` (Ordinaria): Cuando corresponde a un pago que se realiza de manera habitual, como sueldos. + * - `“E”` (Extraordinaria): Para pagos fuera de lo habitual, como liquidaciones, aguinaldos o bonos. + * @default O + * @enum {string} + */ + tipo_nomina?: 'O' | 'E' + /** Fecha de pago de la nómina al trabajador. Si se omite, se utiliza la fecha y hora actuales. */ + fecha_pago?: components['schemas']['DateOrDateTime'] + /** Fecha inicial del periodo de pago. */ + fecha_inicial_pago?: components['schemas']['DateOrDateTime'] + /** Fecha final del periodo de pago. */ + fecha_final_pago?: components['schemas']['DateOrDateTime'] + /** Número de días pagados. Puede ser entero o fracción. */ + num_dias_pagados?: number + } + NominaComplementDataNestedInput: { + emisor?: components['schemas']['NominaEmisorInput'] + receptor?: components['schemas']['NominaReceptorInput'] + percepciones?: components['schemas']['NominaPercepcionesInput'] + /** Arreglo de objetos donde se expresan las deducciones aplicables. */ + deducciones?: components['schemas']['NominaDeduccionInput'][] + /** Arreglo de objetos para expresar otros pagos aplicables. */ + otros_pagos?: (components['schemas']['NominaOtroPagoInput'] & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionInput'] + })[] + /** Arreglo de objetos con información de incapacidades. */ + incapacidades?: components['schemas']['NominaIncapacidadInput'][] + } + NominaComplementDataNestedProperties: { + emisor?: components['schemas']['NominaEmisorProperties'] + receptor?: components['schemas']['NominaReceptorProperties'] + percepciones?: components['schemas']['NominaPercepcionesProperties'] + /** Arreglo de objetos donde se expresan las deducciones aplicables. */ + deducciones?: components['schemas']['NominaDeduccionProperties'][] + /** Arreglo de objetos para expresar otros pagos aplicables. */ + otros_pagos?: (components['schemas']['NominaOtroPagoDirectProperties'] & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionProperties'] + })[] + /** Arreglo de objetos con información de incapacidades. */ + incapacidades?: components['schemas']['NominaIncapacidadProperties'][] + } + /** Incapacidad */ + NominaIncapacidadInput: WithRequired< + components['schemas']['NominaIncapacidadProperties'], + 'dias_incapacidad' | 'tipo_incapacidad' + > + NominaIncapacidadProperties: { + /** Número de días enteros que el trabajador se incapacitó en el periodo. */ + dias_incapacidad?: number + /** Clave del catálogo [Tipo de Incapacidad](#tipo-de-incapacidad). */ + tipo_incapacidad?: string + /** Monto del importe monetario de la incapacidad. */ + importe_monetario?: number + } + /** OtroPago */ + NominaOtroPagoInput: WithRequired< + components['schemas']['NominaOtroPagoDirectProperties'], + 'tipo_otro_pago' | 'clave' | 'importe' + > & { + compensacion_saldos_a_favor?: components['schemas']['NominaCompensacionInput'] + } + NominaOtroPagoDirectProperties: { + /** Clave del catálogo [Tipo de Otro Pago](#tipo-de-otro-pago). */ + tipo_otro_pago?: string + /** Clave de otro pago de nómina propia de la contabilidad de cada patrón. */ + clave?: string + /** Descripción alternativa correspondiente a la clave utilizada. */ + concepto?: string + /** Importe por concepto de otro pago. */ + importe?: number + /** + * Subsidio causado conforme a la tabla del subsidio para el empleo + * publicada en el Anexo 8 de la Resolución Miscelánea Fiscal vigente. + * + * Este valor será insertado dentro del nodo `SubsidioAlEmpleo`, y es + * requerido cuando el valor de `tipo_otro_pago` es `"002"`. + */ + subsidio_causado?: number + } + NominaCompensacionInput: WithRequired< + components['schemas']['NominaCompensacionProperties'], + 'saldo_a_favor' | 'ano' | 'remanente_sal_fav' + > + /** Objeto con información referente a la compensación de saldos a favor de un trabajador. */ + NominaCompensacionProperties: { + /** Monto por saldo a favor determinado por el patrón al trabajador en periodos o ejercicios anteriores. */ + saldo_a_favor?: number + /** Año en que se determinó el saldo a favor del trabajador. */ + ano?: number + /** Remanente del saldo a favor del trabajador. */ + remanente_sal_fav?: number + } + /** Deduccion */ + NominaDeduccionInput: WithRequired< + components['schemas']['NominaDeduccionProperties'], + 'tipo_deduccion' | 'clave' | 'importe' + > + NominaDeduccionProperties: { + /** Clave del catálogo [Tipo de deducción](#tipo-de-deducción). */ + tipo_deduccion?: string + /** Concepto de la deducción. Si no se envía, se utilizará la descripción del catálogo del tipo de deducción. */ + concepto?: string + /** Clave de control interno que asigna el patrón a cada deducción (descuento) de nómina propia de su contabilidad. */ + clave?: string + /** Importe del concepto de deducción. */ + importe?: number + } + /** + * Percepciones + * Objeto para indicar las percepciones aplicables. + */ + NominaPercepcionesInput: { + /** Objeto con información detallada de cada percepción. */ + percepcion: components['schemas']['NominaPercepcionInput'][] + jubilacion_pension_retiro?: components['schemas']['NominaJubilacionInput'] + separacion_indemnizacion?: components['schemas']['NominaSeparacionInput'] + } + /** + * Percepciones + * Objeto para indicar las percepciones aplicables. + */ + NominaPercepcionesProperties: { + /** Objeto con información detallada de cada percepción. */ + percepcion?: components['schemas']['NominaPercepcionProperties'][] + jubilacion_pension_retiro?: components['schemas']['NominaJubilacionProperties'] + separacion_indemnizacion?: components['schemas']['NominaSeparacionProperties'] + } + /** Separacion */ + NominaSeparacionInput: WithRequired< + components['schemas']['NominaSeparacionProperties'], + | 'total_pagado' + | 'num_anos_servicio' + | 'ultimo_sueldo_mens_ord' + | 'ingreso_acumulable' + | 'ingreso_no_acumulable' + > + /** + * Jubilacion + * Objeto con información detallada de pagos por separación (despido) o indemnización. + */ + NominaSeparacionProperties: { + /** Monto total pagado por concepto de separación o indemnización. */ + total_pagado?: number + /** Años de servicio que laboró el trabajador, redondeado al entero inmediato superior. */ + num_anos_servicio?: number + /** Último sueldo mensual ordinario percibido por el trabajador. */ + ultimo_sueldo_mens_ord?: number + /** Monto por ingresos acumulables. */ + ingreso_acumulable?: number + /** Monto por ingresos no acumulables. */ + ingreso_no_acumulable?: number + } + /** Jubilacion */ + NominaJubilacionInput: WithRequired< + components['schemas']['NominaJubilacionProperties'], + 'ingreso_acumulable' | 'ingreso_no_acumulable' + > + /** Objeto con información detallada de pagos por jubilación, pensiones o haberes de retiro. */ + NominaJubilacionProperties: { + /** Monto total del pago entregado en una sola exhibición. */ + total_una_exhibicion?: number + /** Monto total del pago entregado en parcialidades. */ + total_parcialidad?: number + /** Monto diario percibido por el trabajador cuando el pago se realiza en parcialidades. */ + monto_diario?: number + /** Ingresos acumulables percibidos por el trabajador. */ + ingreso_acumulable?: number + /** Ingresos no acumulables percibidos por el trabajador. */ + ingreso_no_acumulable?: number + } + /** Percepcion */ + NominaPercepcionProperties: components['schemas']['NominaPercepcionDirectProperties'] & + components['schemas']['NominaPercepcionNestedProperties'] + /** + * Percepcion + * La entrada utiliza las claves de percepción del catálogo publicado. La clave 019 requiere horas_extra. + */ + NominaPercepcionInput: (WithRequired< + components['schemas']['NominaPercepcionDirectProperties'], + 'tipo_percepcion' | 'clave' | 'importe_gravado' | 'importe_exento' + > & + components['schemas']['NominaPercepcionNestedInput']) & + ( + | { + /** @constant */ + tipo_percepcion?: '019' + horas_extra: components['schemas']['NominaHorasExtraInput'][] + } + | { + /** @enum {string} */ + tipo_percepcion?: + | '001' + | '002' + | '003' + | '004' + | '005' + | '006' + | '009' + | '010' + | '011' + | '012' + | '013' + | '014' + | '015' + | '020' + | '021' + | '022' + | '023' + | '024' + | '025' + | '026' + | '027' + | '028' + | '029' + | '030' + | '031' + | '032' + | '033' + | '034' + | '035' + | '036' + | '037' + | '038' + | '039' + | '044' + | '045' + | '046' + | '047' + | '048' + | '049' + | '050' + | '051' + | '052' + | '053' + | '054' + | '055' + | '056' + } + ) + NominaPercepcionDirectProperties: { + /** Clave del catálogo [Tipo de percepción](#tipo-de-percepcion). */ + tipo_percepcion?: string + /** Concepto de la percepción. Si no se envía, se utilizará la descripción del catálogo del tipo de percepción. */ + concepto?: string + /** Clave de control interno que asigna el patrón a cada percepción de nómina propia de su contabilidad. */ + clave?: string + /** Importe gravado por el concepto indicado en el tipo de percepción. */ + importe_gravado?: number + /** Importe exento por el concepto indicado en el tipo de percepción. */ + importe_exento?: number + } + NominaPercepcionNestedInput: { + acciones_o_titulos?: components['schemas']['NominaAccionesInput'] + /** Arreglo de objetos para expresar las horas extra aplicables. Requerido cuando el tipo de percepción es “019” (Horas extras). */ + horas_extra?: components['schemas']['NominaHorasExtraInput'][] + } + NominaPercepcionNestedProperties: { + acciones_o_titulos?: components['schemas']['NominaAccionesProperties'] + /** Arreglo de objetos para expresar las horas extra aplicables. Requerido cuando el tipo de percepción es “019” (Horas extras). */ + horas_extra?: components['schemas']['NominaHorasExtraProperties'][] + } + /** HorasExtra */ + NominaHorasExtraInput: WithRequired< + components['schemas']['NominaHorasExtraProperties'], + 'dias' | 'tipo_horas' | 'horas_extra' | 'importe_pagado' + > + /** HorasExtra */ + NominaHorasExtraProperties: { + /** Número de días en que el trabajador laboró horas extra adicionales a su jornada normal de trabajo. */ + dias?: number + /** Clave del catálogo [Tipo de Horas](#tipo-de-Horas). */ + tipo_horas?: string + /** Número de horas extra trabajadas en el periodo. */ + horas_extra?: number + /** Importe pagado por las horas extra. */ + importe_pagado?: number + } + /** Accion */ + NominaAccionesInput: WithRequired< + components['schemas']['NominaAccionesProperties'], + 'valor_mercado' | 'precio_al_otorgarse' + > + /** + * Accion + * Objeto para expresar ingresos por acciones o títulos valor que representan bienes. Es requerido cuando existan ingresos por sueldos derivados de adquisición de acciones o títulos. + */ + NominaAccionesProperties: { + /** Valor de mercado de las Acciones o Títulos valor al ejercer la opción. */ + valor_mercado?: number + /** Precio establecido al otorgarse la opción de ingresos en acciones o títulos valor. */ + precio_al_otorgarse?: number + } + /** + * Receptor + * Información del trabajador. + */ + NominaReceptorProperties: components['schemas']['NominaReceptorDirectProperties'] & + components['schemas']['NominaReceptorNestedProperties'] + /** + * Receptor + * Información del trabajador. + */ + NominaReceptorInput: WithRequired< + components['schemas']['NominaReceptorDirectProperties'], + | 'curp' + | 'tipo_contrato' + | 'tipo_regimen' + | 'num_empleado' + | 'periodicidad_pago' + | 'clave_ent_fed' + > & + components['schemas']['NominaReceptorNestedInput'] + NominaReceptorDirectProperties: { + /** CURP del trabajador. */ + curp?: string + /** Número de seguridad social. */ + num_seguridad_social?: string + /** Fecha de inicio de la relación laboral entre el empleador y el empleado. */ + fecha_inicio_rel_laboral?: components['schemas']['DateOrDateTime'] + /** + * Antigüedad del empleado en el formato especificado por el SAT. Si se envía un `string`, se espera que éste contenga la antigüedad en el formato que especifica el SAT. Si se envía el valor booleano `false`, este campo no se incluirá en la factura. Si se envía el valor booleano `true` y `fecha_inicio_rel_laboral` existe, este valor se calculará con la diferencia entre la fecha de inicio de relación laboral y la fecha de pago. + * @default true + */ + antiguedad?: string | boolean + /** Clave del catálogo del SAT [Tipo de Contrato](#tipo-de-contrato). */ + tipo_contrato?: string + /** + * Indica si el trabajador está asociado a un sindicato. + * @default false + */ + sindicalizado?: boolean + /** Clave del catálogo del SAT [Tipo de Jornada](#tipo-de-jornada). */ + tipo_jornada?: string + /** Clave del catálogo del SAT [Tipo de Régimen](#régimen-fiscal). */ + tipo_regimen?: string + /** Número interno de empleado, asignado por el empleador. */ + num_empleado?: string + /** Nombre del departamento o área a la que pertenece el trabajador. */ + departamento?: string + /** Nombre del puesto asignado al empleado o el nombre de la actividad que realiza. */ + puesto?: string + /** Clave del catálogo del SAT [Riesgo del Puesto](#riesgo-del-puesto). */ + riesgo_puesto?: string + /** Clave del catálogo del SAT [Periodicidad de Pago](#periodicidad-del-pago). */ + periodicidad_pago?: string + /** Clave del banco de acuerdo al catálogo del SAT “Bancos” que puedes consultar utilizando nuestra [herramienta de búsqueda](https://dashboard.facturapi.io/catalogs/bank). */ + banco?: string + /** Número de cuenta bancaria (11 caracteres) o número de teléfono celular (10 caracteres) o número de tarjeta (15 ó 16 caracteres) o la CLABE (18 caracteres) o número de monedero electrónico donde se realiza el depósito de nómina. */ + cuenta_bancaria?: string + /** Importe de la retribución en efectivo por cuota diaria, gratificaciones, percepciones, alimentación, habitación, primas, comisiones, prestaciones en especie, etc. */ + salario_base_cot_apor?: number + /** Salario que se integra con los pagos hechos en efectivo por cuota diaria, gratificaciones, percepciones, habitación, primas, comisiones, prestaciones en especie y cualquier otra cantidad o prestación que se entregue al trabajador por su trabajo. */ + salario_diario_integrado?: number + /** Clave de la entidad federativa en donde el trabajador prestó sus servicios al empleador, que puedes consultar utilizando nuestra [herramienta de búsqueda](https://dashboard.facturapi.io/catalogs/state). */ + clave_ent_fed?: string + } + NominaReceptorNestedProperties: { + /** Arreglo de objetos para expresar información sobre la empresa que se beneficia del trabajo del empleado, en casos donde el emisor preste servicios de subcontratación. */ + sub_contratacion?: components['schemas']['NominaSubContratacionProperties'][] + } + NominaReceptorNestedInput: { + /** Arreglo de objetos para expresar información sobre la empresa que se beneficia del trabajo del empleado, en casos donde el emisor preste servicios de subcontratación. */ + sub_contratacion?: (components['schemas']['NominaSubContratacionRequiredProperties'] & + components['schemas']['NominaSubContratacionProperties'])[] + } + NominaSubContratacionRequiredProperties: Record + NominaSubContratacionProperties: { + /** RFC de la persona o empresa que subcontrata, es decir, de la persona o empresa en donde el trabajador prestó directamente sus servicios. */ + rfc_labora?: string + /** Porcentaje de tiempo en que el trabajador prestó sus servicios a la persona o empresa que lo subcontrató. */ + porcentaje_tiempo?: number + } + NominaEntidadSncfInput: { + /** @enum {string} */ + origen_recurso: 'IP' | 'IF' | 'IM' + monto_recurso_propio?: number + } & ( + | { + /** @constant */ + origen_recurso?: 'IM' + monto_recurso_propio: number + } + | { + /** @enum {string} */ + origen_recurso?: 'IP' | 'IF' + } + ) + NominaEmisorInput: components['schemas']['NominaEmisorProperties'] & { + entidad_sncf?: components['schemas']['NominaEntidadSncfInput'] + } + /** + * Emisor + * Información del emisor, en caso de ser requerida. + */ + NominaEmisorProperties: { + /** Requerido cuando el empleador es persona física. CURP del empleador. */ + curp?: string + /** Clave de registro patronal asignada por la institución de seguridad social al patrón. */ + registro_patronal?: string + /** RFC de la persona que fungió como patrón. Se usa cuando el pago se realiza a través de un tercero. */ + rfc_patron_origen?: string + /** Información para que las entidades adheridas al Sistema Nacional de Coordinación Fiscal realicen la identificación del origen de los recursos. */ + entidad_sncf?: { + /** + * Clave de origen de recurso. + * + * - `“IP”`: Ingresos Propios + * - `“IF”`: Ingresos Federales + * - `“IM”`: Ingresos mixtos. + * @enum {string} + */ + origen_recurso?: 'IP' | 'IF' | 'IM' + /** Importe de recursos propios. Requerido cuando el origen del recurso es por ingresos mixtos. */ + monto_recurso_propio?: number + } + } + /** Complement */ + PagoOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: 'pago' | 'custom' + } & ( + | components['schemas']['PagoComplementProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + PagoOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'pago' | 'custom' + } & ( + | components['schemas']['PagoComplementInput'] + | components['schemas']['CustomComplementInput'] + ) + PagoComplementProperties: { + /** @constant */ + type: 'pago' + } & { + data?: components['schemas']['PagoComplementDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'pago' + } + PagoComplementInput: { + /** @constant */ + type: 'pago' + } & { + data?: components['schemas']['PagoComplementDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'pago' + } + InvoiceComplementInput: + | components['schemas']['PagoComplementInput'] + | components['schemas']['NominaComplementInput'] + | components['schemas']['CartaPorteInput'] + | components['schemas']['ComercioExteriorInput'] + | components['schemas']['LeyendasFiscalesInput'] + | components['schemas']['CustomComplementInput'] + InvoiceComplementProperties: + | components['schemas']['PagoComplementProperties'] + | components['schemas']['NominaComplementProperties'] + | components['schemas']['CartaPorteProperties'] + | components['schemas']['ComercioExteriorProperties'] + | components['schemas']['LeyendasFiscalesProperties'] + | components['schemas']['CustomComplementProperties'] + PagoComplementDataProperties: components['schemas']['PaymentProperties'][] + PaymentProperties: components['schemas']['PaymentInput'] & { + /** Format: date-time */ + date: Date + } + /** + * PagoComplementData + * Pagos a incluir en este comprobante. Lo más común es incluir un sólo pago. Un caso en el que se debe de agregar más de uno es cuando el pago se realiza con 2 formas de pago distintas; por ejemplo, cuando se paga una parte con tarjeta y otra en efectivo. + */ + PagoComplementDataInput: + | components['schemas']['PaymentInput'] + | components['schemas']['PaymentInput'][] + /** Complement */ + NominaOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: 'nomina' | 'custom' + } & ( + | components['schemas']['NominaComplementProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + NominaOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'nomina' | 'custom' + } & ( + | components['schemas']['NominaComplementInput'] + | components['schemas']['CustomComplementInput'] + ) + NominaComplementProperties: { + /** @constant */ + type: 'nomina' + } & { + data?: components['schemas']['NominaComplementDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'nomina' + } + NominaComplementInput: { + /** @constant */ + type: 'nomina' + } & { + data?: components['schemas']['NominaComplementDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'nomina' + } + CartaPorteProperties: { + /** @constant */ + type: 'carta_porte' + } & { + data?: components['schemas']['CartaPorteDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'carta_porte' + } + CartaPorteInput: { + /** @constant */ + type: 'carta_porte' + } & { + data?: components['schemas']['CartaPorteDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'carta_porte' + } + ComercioExteriorProperties: { + /** @constant */ + type: 'comercio_exterior' + } & { + data?: components['schemas']['ComercioExteriorDataProperties'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'comercio_exterior' + } + ComercioExteriorInput: { + /** @constant */ + type: 'comercio_exterior' + } & { + data?: components['schemas']['ComercioExteriorDataInput'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'comercio_exterior' + } + LeyendasFiscalesProperties: { + /** @constant */ + type: 'leyendas_fiscales' + } & { + data?: components['schemas']['LeyendasFiscalesData'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'leyendas_fiscales' + } + LeyendasFiscalesInput: { + /** @constant */ + type: 'leyendas_fiscales' + } & { + data?: components['schemas']['LeyendasFiscalesData'] + } & { + /** + * discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: 'leyendas_fiscales' + } + /** Complement */ + CartaPorteOrCustomComplementProperties: { + /** + * Tipo de complemento. + * @enum {string} + */ + type?: + 'carta_porte' | 'comercio_exterior' | 'leyendas_fiscales' | 'custom' + } & ( + | components['schemas']['CartaPorteProperties'] + | components['schemas']['ComercioExteriorProperties'] + | components['schemas']['LeyendasFiscalesProperties'] + | components['schemas']['CustomComplementProperties'] + ) + /** Complement */ + CartaPorteOrCustomComplementInput: { + /** + * Tipo de complemento. + * @enum {string} + */ + type: 'carta_porte' | 'comercio_exterior' | 'leyendas_fiscales' | 'custom' + } & ( + | components['schemas']['CartaPorteInput'] + | components['schemas']['ComercioExteriorInput'] + | components['schemas']['LeyendasFiscalesInput'] + | components['schemas']['CustomComplementInput'] + ) + /** + * LeyendasFiscales + * Complemento de Leyendas Fiscales versión 1.0. + */ + LeyendasFiscalesData: { + /** Leyendas fiscales a incluir en el comprobante. */ + leyendas: { + /** Disposición fiscal aplicable a la leyenda. */ + disposicion_fiscal?: string + /** Norma que regula la leyenda. */ + norma?: string + /** Texto de la leyenda fiscal. */ + texto_leyenda: string + }[] + } + /** + * CartaPorte + * Complemento Carta Porte versión 3.1. (Beta) + */ + CartaPorteDataProperties: { + /** Identificador único de la Carta Porte. */ + IdCCP: string + /** Indica si el transporte es internacional. */ + TranspInternac: string + /** Entrada o salida de mercancías. */ + EntradaSalidaMerc?: string + /** País de origen o destino. */ + PaisOrigenDestino?: string + /** Vía de entrada o salida. */ + ViaEntradaSalida?: string + /** Distancia total recorrida. */ + TotalDistRec?: number + /** Registro del programa ISTMO. */ + RegistroISTMO?: string + /** Polo origen. */ + UbicacionPoloOrigen?: string + /** Polo destino. */ + UbicacionPoloDestino?: string + /** Objeto con los regímenes aduaneros aplicables. */ + RegimenesAduaneros?: Record + /** Arreglo de ubicaciones. */ + Ubicaciones: { + /** Atributo requerido para precisar si el tipo de ubicación corresponde al origen o destino de las ubicaciones para el traslado de los bienes y/o mercancías en los distintos medios de transporte. Valores: "Origen" | "Destino". */ + TipoUbicacion: string + /** Atributo condicional para registrar una clave que identifique el punto de salida o entrada de los bienes y/o mercancías. Formato: "OR" o "DE" seguido de 6 dígitos numéricos (expresión regular (OR|DE)[0-9]{6}). */ + IDUbicacion?: string + /** Atributo requerido para registrar el RFC del remitente o destinatario de los bienes y/o mercancías que se trasladan. */ + RFCRemitenteDestinatario: string + /** Atributo opcional para registrar el nombre del remitente o destinatario de los bienes y/o mercancías (longitud 1 a 254 caracteres). */ + NombreRemitenteDestinatario?: string + /** Atributo condicional para el número de identificación o registro fiscal del país de residencia del remitente o destinatario cuando se trate de residentes en el extranjero (longitud 6 a 40 caracteres). */ + NumRegIdTrib?: string + /** Atributo condicional para registrar la clave del país de residencia fiscal conforme al catálogo c_Pais (ISO 3166-1). */ + ResidenciaFiscal?: string + /** Atributo condicional para la clave de la estación de origen o destino conforme al catálogo c_Estaciones del complemento Carta Porte y al tipo de transporte. */ + NumEstacion?: string + /** Atributo condicional para el nombre de la estación de origen o destino conforme al catálogo c_Estaciones (longitud 1 a 50 caracteres). */ + NombreEstacion?: string + /** Atributo condicional para registrar el tipo de puerto de origen o destino en transporte marítimo. Valores: "Altura" | "Cabotaje". */ + NavegacionTrafico?: string + /** Atributo requerido para registrar la fecha y hora estimada de salida o llegada en formato AAAA-MM-DDThh:mm:ss. */ + FechaHoraSalidaLlegada: string + /** Atributo condicional para registrar el tipo de estación por la que pasan las mercancías conforme al catálogo c_TipoEstacion. */ + TipoEstacion?: string + /** Atributo condicional para registrar en kilómetros la distancia recorrida entre la ubicación de origen y la de destino parcial o final. */ + DistanciaRecorrida?: number + Domicilio?: components['schemas']['CartaPorteDomicilio'] + }[] + Mercancias: components['schemas']['CartaPorteMercancias'] + /** Figuras de transporte. */ + FiguraTransporte?: { + /** Atributo requerido. Clave que identifica el tipo de figura de transporte conforme al catálogo correspondiente (operador, propietario, arrendatario, notificado). Debe coincidir con c_TipoFigura. */ + TipoFigura: string + /** RFC del operador/propietario/arrendatario o figura interveniente. */ + RFCFigura?: string + /** Número de licencia del operador cuando TipoFigura corresponde a operador. */ + NumLicencia?: string + /** Nombre o razón social de la figura de transporte (requerido). */ + NombreFigura: string + /** Número de registro fiscal en el extranjero de la figura cuando aplica. */ + NumRegIdTribFigura?: string + /** Clave del país de residencia fiscal de la figura (c_Pais) cuando es extranjero. */ + ResidenciaFiscalFigura?: string + /** Arreglo opcional con las partes del transporte que se relacionan a la figura. */ + PartesTransporte?: { + /** Clave de la parte del transporte conforme al catálogo c_ParteTransporte. */ + ParteTransporte: string + }[] + /** Domicilio asociado a la figura del transporte. */ + Domicilio?: components['schemas']['CartaPorteDomicilio'] + }[] + } + CartaPorteDataInput: components['schemas']['CartaPorteDataProperties'] + /** + * ComercioExterior + * Complemento Comercio Exterior versión 2.0. + */ + ComercioExteriorDataProperties: { + /** + * @default 2.0 + * @enum {string} + */ + Version?: '2.0' + /** Clave del catálogo c_MotivoTraslado. */ + MotivoTraslado?: string + /** Clave del pedimento (catálogo c_ClavePedimento). */ + ClaveDePedimento: string + /** + * Indica si existe certificado de origen. + * @enum {integer} + */ + CertificadoOrigen: 0 | 1 + /** Número de certificado de origen. */ + NumCertificadoOrigen?: string + /** Número de exportador confiable. */ + NumeroExportadorConfiable?: string + /** Clave del INCOTERM (catálogo c_INCOTERM). */ + Incoterm?: string + Observaciones?: string + /** Tipo de cambio USD. */ + TipoCambioUSD: number + /** Total en USD. */ + TotalUSD: number + /** Objeto con información del emisor del complemento. Requerido cuando el domicilio y CURP del emisor no se toman de la organización que emite el complemento. */ + Emisor?: components['schemas']['ComercioExteriorEmisor'] | boolean + Propietario?: ( + | components['schemas']['ComercioExteriorPropietario'] + | components['schemas']['CustomerComercioExterior'] + )[] + Receptor?: + | components['schemas']['ComercioExteriorReceptor'] + | components['schemas']['CustomerComercioExterior'] + Destinatario?: ( + | components['schemas']['ComercioExteriorDestinatario'] + | components['schemas']['CustomerComercioExterior'] + )[] + Mercancias: components['schemas']['ComercioExteriorMercancias'] + } + ComercioExteriorDataInput: components['schemas']['ComercioExteriorDataProperties'] + ComercioExteriorDomicilio: { + Calle: string + NumeroExterior?: string + NumeroInterior?: string + Colonia?: string + Localidad?: string + Referencia?: string + Municipio?: string + Estado: string + /** Clave del catálogo c_Pais. */ + Pais: string + CodigoPostal: string + } + ComercioExteriorEmisor: { + Domicilio: components['schemas']['ComercioExteriorDomicilio'] + Curp?: string + } + ComercioExteriorPropietario: { + NumRegIdTrib: string + /** Clave del catálogo c_Pais. */ + ResidenciaFiscal: string + } + ComercioExteriorReceptor: { + Domicilio?: components['schemas']['ComercioExteriorDomicilio'] + NumRegIdTrib?: string + } + ComercioExteriorDestinatario: { + Domicilio: components['schemas']['ComercioExteriorDomicilio'][] + NumRegIdTrib?: string + Nombre?: string + } + ComercioExteriorDescripcionesEspecificas: { + Marca: string + Modelo?: string + SubModelo?: string + NumeroSerie?: string + } + ComercioExteriorMercancia: { + DescripcionesEspecificas?: components['schemas']['ComercioExteriorDescripcionesEspecificas'][] + NoIdentificacion: string + /** Clave del catálogo c_FraccionArancelaria. */ + FraccionArancelaria?: string + CantidadAduana?: number + /** Clave del catálogo c_UnidadAduana. */ + UnidadAduana?: string + ValorUnitarioAduana?: number + ValorDolares: number + } + ComercioExteriorMercancias: { + Mercancia: components['schemas']['ComercioExteriorMercancia'][] + } + CartaPorteCantidadTransporta: { + Cantidad: number + IDOrigen: string + IDDestino: string + /** Clave del medio de transporte. */ + CvesTransporte?: string + } + CartaPorteDetalleMercancia: { + /** Clave de la unidad de peso de la mercancía conforme al catálogo correspondiente. */ + UnidadPesoMerc: string + /** Peso bruto de la mercancía incluyendo embalajes y tare. */ + PesoBruto: number + /** Peso neto de la mercancía sin incluir embalajes ni tara. */ + PesoNeto: number + /** Peso de la tara (contenedores, embalajes) asociado a la mercancía. */ + PesoTara: number + /** Número de piezas que conforman la mercancía detallada. */ + NumPiezas?: number + } + /** RFC del importador cuando aplica. */ + CartaPorteDocumentacionAduanera: { + /** Tipo de documento aduanero (pedimento, guía, conocimiento) relacionado. */ + TipoDocumento?: string + /** Número de pedimento de importación/exportación. */ + NumPedimento?: string + /** Identificador alterno del documento aduanero. */ + IdentDocAduanero?: string + RFCImpo?: string + } + CartaPorteGuiaIdentificacion: { + /** Número de la guía de identificación asociada a la mercancía. */ + NumeroGuiaIdentificacion?: string + /** Descripción detallada de la guía de identificación. */ + DescripGuiaIdentificacion?: string + /** Peso amparado por la guía de identificación. */ + PesoGuiaIdentificacion?: number + } + CartaPorteMercancia: { + /** Clave del bien o producto transportado (catCartaPorte:c_BienesTransp). */ + BienesTransp: string + /** Clave STCC para transporte ferroviario cuando corresponda. */ + ClaveSTCC?: string + /** Descripción comercial del bien transportado. */ + Descripcion: string + /** Cantidad total de unidades del bien. */ + Cantidad: number + /** Clave de unidad (c_ClaveUnidad) aplicable a la cantidad. */ + ClaveUnidad: string + /** Texto descriptivo de la unidad de medida. */ + Unidad?: string + /** Dimensiones físicas de la mercancía (largo x ancho x alto) si aplica. */ + Dimensiones?: string + /** Indicador de si la mercancía es material peligroso ("Sí" / "No"). */ + MaterialPeligroso?: string + /** Clave del material peligroso (c_MaterialPeligroso) cuando MaterialPeligroso es Sí. */ + CveMaterialPeligroso?: string + /** Clave del tipo de embalaje utilizado (c_TipoEmbalaje). */ + Embalaje?: string + /** Descripción adicional del embalaje. */ + DescripEmbalaje?: string + /** Sector regulado por COFEPRIS al que pertenece el producto. */ + SectorCOFEPRIS?: string + /** Nombre del ingrediente activo (productos regulados). */ + NombreIngredienteActivo?: string + /** Nombre químico del producto cuando aplica. */ + NomQuimico?: string + /** Denominación genérica del producto farmacéutico. */ + DenominacionGenericaProd?: string + /** Denominación distintiva (marca) del producto farmacéutico. */ + DenominacionDistintivaProd?: string + /** Nombre o razón social del fabricante. */ + Fabricante?: string + /** Fecha de caducidad del producto (AAAAMMDD o formato aplicable). */ + FechaCaducidad?: string + /** Número de lote del medicamento. */ + LoteMedicamento?: string + /** Forma farmacéutica (tableta, cápsula, solución, etc.). */ + FormaFarmaceutica?: string + /** Condiciones especiales de transporte (refrigeración, frágil, etc.). */ + CondicionesEspTransp?: string + /** Registro sanitario o folio de autorización. */ + RegistroSanitarioFolioAutorizacion?: string + /** Número de permiso de importación. */ + PermisoImportacion?: string + /** Folio VUCEM de importación. */ + FolioImpoVUCEM?: string + /** Número CAS para sustancias químicas. */ + NumCAS?: string + /** Razón social de la empresa importadora. */ + RazonSocialEmpImp?: string + /** Número de registro sanitario o plaguicida COFEPRIS. */ + NumRegSanPlagCOFEPRIS?: string + /** Información adicional del fabricante. */ + DatosFabricante?: string + /** Información del formulador del producto. */ + DatosFormulador?: string + /** Información del maquilador (si aplica). */ + DatosMaquilador?: string + /** Uso autorizado del producto. */ + UsoAutorizado?: string + /** Peso en kilogramos de la mercancía (puede ser peso neto o bruto según contexto). */ + PesoEnKg: number + /** Valor monetario de la mercancía. */ + ValorMercancia?: number + /** Clave de moneda (c_Moneda) del valor de la mercancía. */ + Moneda?: string + /** Fracción arancelaria aplicable (c_FraccionArancelaria). */ + FraccionArancelaria?: string + /** UUID asociado al complemento de Comercio Exterior relacionado. */ + UUIDComercioExt?: string + /** Tipo de materia prima (si aplica para minerales, sustancias, etc.). */ + TipoMateria?: string + /** Descripción de la materia prima. */ + DescripcionMateria?: string + /** Documentos aduaneros asociados a la mercancía. */ + DocumentacionAduanera?: components['schemas']['CartaPorteDocumentacionAduanera'][] + /** Guías de identificación asociadas. */ + GuiasIdentificacion?: components['schemas']['CartaPorteGuiaIdentificacion'][] + /** Detalle de cantidades transportadas por origen/destino. */ + CantidadTransporta?: components['schemas']['CartaPorteCantidadTransporta'][] + /** Detalle de pesos y piezas de la mercancía. */ + DetalleMercancia?: components['schemas']['CartaPorteDetalleMercancia'][] + } + CartaPorteIdentificacionVehicular: { + /** Configuración vehicular (catCartaPorte:c_ConfigAutotransporte) del vehículo primario. */ + ConfigVehicular: string + /** Peso bruto vehicular máximo permitido. */ + PesoBrutoVehicular: number + /** Placa del vehículo motor. */ + PlacaVM: string + /** Año modelo del vehículo motor. */ + AnioModeloVM: string + } + CartaPorteSeguros: { + /** Nombre de la aseguradora de responsabilidad civil. */ + AseguraRespCivil: string + /** Número de póliza de responsabilidad civil. */ + PolizaRespCivil: string + /** Aseguradora contra daños al medio ambiente. */ + AseguraMedAmbiente?: string + /** Número de póliza de medio ambiente. */ + PolizaMedAmbiente?: string + /** Aseguradora de la carga. */ + AseguraCarga?: string + /** Número de póliza de la carga. */ + PolizaCarga?: string + /** Prima total de los seguros contratados. */ + PrimaSeguro?: number + } + CartaPorteRemolque: { + /** Subtipo de remolque (catCartaPorte:c_SubTipoRem). */ + SubTipoRem?: string + /** Placa del remolque. */ + Placa?: string + } + CartaPorteAutotransporte: { + /** Clave del permiso SCT del autotransporte. */ + PermSCT: string + /** Número del permiso SCT. */ + NumPermisoSCT: string + /** Datos de identificación del vehículo principal. */ + IdentificacionVehicular: components['schemas']['CartaPorteIdentificacionVehicular'] + /** Información de seguros aplicables. */ + Seguros: components['schemas']['CartaPorteSeguros'] + /** Lista de remolques acoplados. */ + Remolques?: components['schemas']['CartaPorteRemolque'][] + } + CartaPorteContenedorMaritimo: { + /** Tipo de contenedor marítimo (ISO / catálogo SAT). */ + TipoContenedor?: string + /** Matrícula o número identificador del contenedor. */ + MatriculaContenedor?: string + /** Número de precinto o sello de seguridad. */ + NumPrecinto?: string + /** Identificador CCP relacionado cuando se reutiliza información. */ + IdCCPRelacionado?: string + /** Placa del vehículo motor asociado (si aplica en transbordo). */ + PlacaVMCCP?: string + /** Fecha de certificación CCP del contenedor. */ + FechaCertificacionCCP?: string + RemolquesCCP?: { + /** Subtipo de remolque relacionado (CCP). */ + SubTipoRemCCP?: string + /** Placa del remolque relacionado (CCP). */ + PlacaCCP?: string + }[] + } + CartaPorteTransporteMaritimo: { + /** Clave del permiso SCT de la embarcación. */ + PermSCT: string + /** Número de permiso SCT de la embarcación. */ + NumPermisoSCT: string + /** Nombre de la aseguradora marítima. */ + NombreAseg?: string + /** Número de póliza de seguro marítimo. */ + NumPolizaSeguro?: string + /** Tipo de embarcación (catCartaPorte:c_TipoEmbarcacion). */ + TipoEmbarcacion?: string + /** Matrícula de la embarcación. */ + Matricula?: string + /** Número OMI (IMO number) de la embarcación. */ + NumeroOMI?: string + /** Año de construcción de la embarcación. */ + AnioEmbarcacion?: string + /** Nombre propio de la embarcación. */ + NombreEmbarc?: string + /** Nacionalidad o bandera de la embarcación. */ + NacionalidadEmbarc?: string + /** Toneladas de arqueo bruto. */ + UnidadesDeArqBruto?: number + /** Tipo de carga (granel, contenedores, líquidos, etc.). */ + TipoCarga?: string + /** Longitud total de la embarcación (eslora). */ + Eslora?: number + /** Ancho máximo de la embarcación (manga). */ + Manga?: number + /** Calado máximo. */ + Calado?: number + /** Altura del puntal. */ + Puntal?: number + /** Nombre de la línea naviera. */ + LineaNaviera?: string + /** Nombre del agente naviero. */ + NombreAgenteNaviero?: string + /** Número de autorización del agente naviero. */ + NumAutorizacionNaviero?: string + /** Número de viaje o rotación. */ + NumViaje?: string + /** Número de conocimiento de embarque. */ + NumConocEmbarc?: string + /** Permiso temporal de navegación. */ + PermisoTempNavegacion?: string + /** Lista de contenedores asociados al embarque. */ + Contenedor?: components['schemas']['CartaPorteContenedorMaritimo'][] + } + CartaPorteTransporteAereo: { + /** Clave del permiso SCT para transporte aéreo. */ + PermSCT?: string + /** Número de permiso SCT. */ + NumPermisoSCT?: string + /** Matrícula de la aeronave. */ + MatriculaAeronave?: string + /** Nombre de la aseguradora aérea. */ + NombreAseg?: string + /** Número de póliza de seguro de la aeronave. */ + NumPolizaSeguro?: string + /** Número de guía aérea (Air Waybill). */ + NumeroGuia?: string + /** Lugar donde se celebró el contrato de transporte. */ + LugarContrato?: string + /** Código del transportista aéreo. */ + CodigoTransportista?: string + /** RFC del embarcador. */ + RFCEmbarcador?: string + /** Número de registro tributario extranjero del embarcador. */ + NumRegIdTribEmbarc?: string + /** País de residencia fiscal del embarcador. */ + ResidenciaFiscalEmbarc?: string + /** Nombre o razón social del embarcador. */ + NombreEmbarcador?: string + } + CartaPorteDerechosDePaso: { + /** Tipo de derecho de paso ferroviario. */ + TipoDerechoDePaso?: string + /** Kilometraje cubierto/pagado en el derecho de paso. */ + KilometrajePagado?: number + } + CartaPorteContenedorFerroviario: { + /** Tipo de contenedor ferroviario. */ + TipoContenedor?: string + /** Peso del contenedor vacío. */ + PesoContenedorVacio?: number + /** Peso neto de la mercancía contenida. */ + PesoNetoMercancia?: number + } + CartaPorteCarroFerroviario: { + /** Tipo de carro ferroviario. */ + TipoCarro?: string + /** Matrícula o número identificador del carro. */ + MatriculaCarro?: string + /** Número de guía asociado al carro. */ + GuiaCarro?: string + /** Toneladas netas transportadas en el carro. */ + ToneladasNetasCarro?: number + /** Contenedores asociados al carro. */ + Contenedor?: components['schemas']['CartaPorteContenedorFerroviario'][] + } + CartaPorteTransporteFerroviario: { + /** Tipo de servicio ferroviario (regular, intermodal, etc.). */ + TipoDeServicio?: string + /** Tipo de tráfico (nacional, internacional, etc.). */ + TipoDeTrafico?: string + /** Nombre de la aseguradora ferroviaria. */ + NombreAseg?: string + /** Número de póliza de seguro ferroviario. */ + NumPolizaSeguro?: string + /** Lista de derechos de paso aplicados. */ + DerechosDePaso?: components['schemas']['CartaPorteDerechosDePaso'][] + /** Lista de carros ferroviarios involucrados. */ + Carro?: components['schemas']['CartaPorteCarroFerroviario'][] + } + /** Domicilio relacionado a la ubicación en el complemento Carta Porte. */ + CartaPorteDomicilio: { + /** Calle del domicilio de origen y/o destino (requerida en XSD). */ + Calle?: string + /** Número exterior donde se ubica el domicilio. */ + NumeroExterior?: string + /** Número interior del domicilio, si existe. */ + NumeroInterior?: string + /** Colonia o dato análogo del domicilio. */ + Colonia?: string + /** Ciudad, población o distrito del domicilio. */ + Localidad?: string + /** Referencia geográfica adicional (ej. coordenadas GPS). */ + Referencia?: string + /** Municipio, delegación, alcaldía o análogo del domicilio. */ + Municipio?: string + /** Clave de estado, entidad o región (ISO 3166-2 conforme catálogo SAT). */ + Estado: string + /** Clave del país (catálogo c_Pais, ISO 3166-1). */ + Pais: string + /** Código postal del domicilio. */ + CodigoPostal: string + } + CartaPorteMercancias: { + /** Suma del peso bruto total de las mercancías (aéreo y ferroviario). */ + PesoBrutoTotal: number + /** Clave de unidad de medida estandarizada del peso (catCartaPorte:c_ClaveUnidadPeso). */ + UnidadPeso: string + /** Suma de los valores PesoNeto de cada DetalleMercancia. */ + PesoNetoTotal?: number + /** Número total de mercancías (cantidad de nodos Mercancia). */ + NumTotalMercancias: number + /** Importe pagado por la tasación de las mercancías (vía aérea). */ + CargoPorTasacion?: number + /** Indica si aplica logística inversa, recolección o devolución. */ + LogisticaInversaRecoleccionDevolucion?: string + /** Arreglo requerido con las mercancías transportadas. */ + Mercancia: components['schemas']['CartaPorteMercancia'][] + /** Datos del autotransporte de carga federal. */ + Autotransporte?: components['schemas']['CartaPorteAutotransporte'] + /** Datos de la embarcación para transporte marítimo. */ + TransporteMaritimo?: components['schemas']['CartaPorteTransporteMaritimo'] + /** Datos del transporte aéreo utilizado. */ + TransporteAereo?: components['schemas']['CartaPorteTransporteAereo'] + /** Datos del transporte ferroviario utilizado. */ + TransporteFerroviario?: components['schemas']['CartaPorteTransporteFerroviario'] + } + NamespaceRequiredProperties: Record + /** Namespace */ + NamespaceProperties: { + /** Prefijo o nombre del namespace. */ + prefix?: string + /** + * Format: url + * Dirección URL asociada al namespace. + */ + uri?: string + /** + * Format: url + * Dirección URL del esquema de validación XSD. + */ + schema_location?: string + } + CommonAddressProperties: { + /** Nombre de la calle */ + street?: string + /** Número exterior. */ + exterior?: string + /** Número interior. */ + interior?: string + /** Colonia */ + neighborhood?: string + /** Ciudad */ + city?: string + /** Municipio o delegación */ + municipality?: string + /** Código postal */ + zip?: string + } + /** Objeto Webhook */ + Webhook: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['WebhookProperties'] + WebhookSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Webhook'][] + } + WebhookProperties: { + /** Id de la organización la cual se está dando de alta el webhook. */ + organization?: string + /** Ambiente en el cual se está dando de alta el webhook. */ + livemode?: boolean + /** Eventos a los que está suscrito el webhook. El valor "*" puede aparecer en respuestas existentes, pero no se acepta al crear o actualizar un webhook; envía los nombres de eventos explícitos. */ + enabled_events?: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + | '*' + )[] + /** + * Format: uri + * Http ruta para el webhook + */ + url?: string + /** + * Status del webhook + * @enum {string} + */ + status?: WebhookEndpointStatus + /** Secreto para verificar las firmas. Se entrega al crear el webhook. */ + readonly secret?: string + description?: string + } + /** Webhook */ + WebhookCreateInput: { + /** + * Format: uri + * URL del webhook a dar de alta para recibir notificaciones. + */ + url: string + /** Los eventos a los que el webhook se suscribirá. */ + enabled_events: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + )[] + } + /** Webhook */ + WebhookCreateEdit: { + /** + * Estatus del webhook + * @enum {string} + */ + status: WebhookEndpointStatus + /** Los eventos a los que el webhook se suscribirá. */ + enabled_events: ( + | 'receipt.self_invoice_complete' + | 'invoice.cancellation_status_updated' + | 'receipt.status_updated' + | 'invoice.global_invoice_created' + | 'invoice.status_updated' + | 'invoice.created_from_dashboard' + | 'customer.edit_link_completed' + )[] + } + /** Objeto Customer */ + Customer: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['CustomerNonEditableProperties'] & + components['schemas']['CustomerProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + curp?: string + external_id?: string + } + CustomerSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Customer'][] + } + CustomerNonEditableProperties: { + /** + * Enlace a una página alojada donde el cliente puede editar su información una vez. + * Ejemplo: https://auto.facturapi.io/tax-info/abcdWXYZ1234 + */ + edit_link?: string | null + /** + * Format: date-time + * Fecha de expiración del enlace de edición. + */ + edit_link_expires_at?: Date | null + /** + * Format: date-time + * Fecha en la que la información fiscal fue validado por el SAT. + */ + sat_validated_at?: Date | null + } + CustomerProperties: components['schemas']['CustomerCommonProperties'] & { + address?: components['schemas']['CommonAddressProperties'] & { + /** Si el país es México ("MEX"), contiene el nombre del Estado o Entidad Federativa. Para extranjeros contiene el código de Estado de acuerdo al estándar [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2), que puedes consultar en nuestro [Catálogo de Estados](https://dashboard.facturapi.io/catalogs/state). */ + state?: string + /** + * Código de país acorde al estándar [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3), del [Catálogo de Países](https://dashboard.facturapi.io/catalogs/country). + * @default MEX + */ + country?: string + } + } + CustomerCommonProperties: { + /** Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id?: string | null + /** Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). */ + tax_system?: string | null + /** + * Format: email + * Dirección de correo electrónico al cual enviar las facturas generadas. + */ + email?: string + /** Teléfono del cliente. */ + phone?: string | null + /** Uso de CFDI por defecto. */ + default_invoice_use?: string + } + /** Omite los parámetros para eliminar un borrador. Los documentos emitidos requieren motivo; los motivos 01 y 04 también requieren substitution. */ + CancellationQueryInput: + | { + /** @enum {string} */ + motive: '01' | '04' + /** ID de Facturapi o UUID del documento sustituto. */ + substitution: string + } + | { + /** @enum {string} */ + motive: '02' | '03' + substitution?: string + } + | { + motive?: never + substitution?: never + } + /** + * Customer with edit link + * La información del cliente puede estar incompleta cuando createEditLink=true. Los campos enviados deben conservar formatos válidos. + */ + CustomerCreateWithEditLinkInput: components['schemas']['CustomerProperties'] & { + /** Si se envía, debe ser un régimen fiscal válido. Omitirlo permite guardar información fiscal incompleta. */ + tax_system?: string + } + CustomerCreateCommonInput: { + /** Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name: string + /** + * Format: email + * Dirección de correo electrónico al cual enviar las facturas generadas. + */ + email?: string + /** Teléfono del cliente. */ + phone?: string | null + /** Uso de CFDI por defecto. */ + default_invoice_use?: string + } + CustomerNationalAddressInput: WithRequired< + components['schemas']['CommonAddressProperties'], + 'zip' + > & { + state?: string + /** + * @default MEX + * @constant + */ + country?: 'MEX' + } + CustomerForeignAddressInput: components['schemas']['CommonAddressProperties'] & { + /** Código ISO 3166-1 alpha-3 distinto de MEX. Es necesario para aplicar las reglas de cliente extranjero. */ + country: string + state?: string + } + /** + * Cliente nacional + * País MEX, u omitido. Requiere razón social, RFC, régimen fiscal y código postal. Los RFC genéricos usan CustomerGenericCreateInput. + */ + CustomerNationalCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id: string + /** Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). */ + tax_system: string + address: components['schemas']['CustomerNationalAddressInput'] + } + /** + * Cliente extranjero + * Requiere razón social y domicilio con un país explícito distinto de MEX. El identificador fiscal y el código postal son opcionales; el régimen fiscal predeterminado es 616. + */ + CustomerForeignCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** En clientes de México contiene el RFC del cliente. Para extranjeros es opcional y representa el número de registro de identificación tributaria, es decir, el equivalente al RFC en el país del cliente. */ + tax_id?: string | null + /** + * Los clientes extranjeros usan 616. Omitirlo, enviar null o una cadena vacía usa el valor predeterminado. + * @default 616 + * @enum {string|null} + */ + tax_system?: '616' | null | '' + address: components['schemas']['CustomerForeignAddressInput'] + } + /** + * RFC genérico + * RFC de público en general XAXX010101000 o RFC genérico extranjero XEXX010101000. Requiere razón social y RFC. El régimen fiscal predeterminado es 616. Si se envía domicilio mexicano, requiere código postal. + */ + CustomerGenericCreateInput: components['schemas']['CustomerCreateCommonInput'] & { + /** @enum {string} */ + tax_id: 'XAXX010101000' | 'XEXX010101000' + /** + * @default 616 + * @enum {string} + */ + tax_system?: '616' + address?: + | components['schemas']['CustomerNationalAddressInput'] + | components['schemas']['CustomerForeignAddressInput'] + } + /** + * Customer + * Los campos requeridos dependen del país y del RFC. Omitir el país equivale a México. Con createEditLink=true se usa CustomerCreateWithEditLinkInput. + */ + CustomerCreateInput: + | components['schemas']['CustomerNationalCreateInput'] + | components['schemas']['CustomerForeignCreateInput'] + | components['schemas']['CustomerGenericCreateInput'] + /** Product */ + LineItemProductInput: components['schemas']['ProductProperties'] + /** Product */ + LineItemProductEgresoInput: components['schemas']['ProductEgresoProperties'] + /** Product */ + LineItemTrasladoProductInput: { + /** Descripción del bien o servicio como aparecerá en la factura. */ + description: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). */ + product_key?: string + /** + * Clave de unidad de medida, del catálogo del SAT. El valor por default `"H87"` (elemento) es la clave para representar una pieza o unidad de venta (lápiz, cuaderno, televisión, etc). + * Si la unidad de tu producto es kilogramos, litros, horas u otra unidad, te proporcionamos una manera conveniente de encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default H87 + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Elemento + */ + unit_name?: string + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + } + LineItemProduct: { + /** ID del producto base. Sólo presente si se utilizó como base un objeto `Product` guardado previamente. */ + id?: string + } & components['schemas']['ProductProperties'] + Parts: { + /** Descripción del producto o servicio. */ + description?: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra herramienta de búsqueda de claves. */ + product_key?: string + /** Cantidad */ + quantity?: number + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + /** Precio unitario */ + unit_price?: number + /** Nombre de la unidad de medida que expresa la cantidad. */ + unit_name?: string + /** Números de pedimento aduanal asociados a esta parte. */ + customs_keys?: string[] + } + PartInput: WithRequired< + components['schemas']['Parts'], + 'description' | 'product_key' + > + /** Objeto Product */ + Product: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['ProductProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization: string + } + ProductSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Product'][] + } + ProductProperties: WithRequired< + components['schemas']['ProductEditableProperties'], + 'description' | 'product_key' | 'price' + > + ProductEditableProperties: { + /** Descripción del bien o servicio como aparecerá en la factura. */ + description?: string + /** Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). */ + product_key?: string + /** Precio por unidad del bien o servicio. Este valor representará el precio con IVA incluido o sin él, dependiendo del valor de `tax_included`. */ + price?: number + /** + * - `true`: Indica que todos los impuestos aplicables están incluidos en el precio (atributo price) y se desglosarán automáticamente al emitir la factura. + * - `false`: Indica que el atributo price no incluye impuestos, por lo que aquellos impuestos a aplicar se sumarán en el precio final. + * @default true + */ + tax_included?: boolean + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * - `06`: Sí objeto de impuesto, no IVA trasladado. + * - `07`: No traslado de IVA, pero desglose de IEPS. + * - `08`: No traslado de IVA sin desglose de IEPS. + * @default 02 + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** + * Lista de impuestos que deberán aplicarse a este producto. + * + * Resolución cuando `taxes` se omite o es `null`: + * - `taxability` omitido o `"02"`: se agrega IVA trasladado 16%. + * - `taxability` en `"01"`, `"03"`, `"04"`, `"05"`, `"06"` o `"08"`: se guarda `[]`. + * - `taxability = "07"`: la solicitud es inválida; debes enviar al menos un IEPS de traslado y no incluir IVA. + * + * Si envías `taxes` explícitamente, se usa el arreglo enviado. + * @default [ + * { + * "type": "IVA", + * "rate": 0.16 + * } + * ] + */ + taxes?: components['schemas']['BaseTax'][] + /** + * Arreglo de impuestos locales (estatales o municipales), en caso de haberlos. + * @default [] + */ + local_taxes?: components['schemas']['LocalTax'][] + /** + * Clave de unidad de medida, del catálogo del SAT. El valor por default `"H87"` (elemento) es la clave para representar una pieza o unidad de venta (lápiz, cuaderno, televisión, etc). + * Si la unidad de tu producto es kilogramos, litros, horas u otra unidad, puedes encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default H87 + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Elemento + */ + unit_name?: string + /** Identificador de uso interno designado por la empresa. Puede tener cualquier valor. */ + sku?: string + } + ProductEgresoProperties: { + /** Resumen de la operación en una sola descripción. Deben mencionarse cada uno de los productos que contempla el descuento, devolución o bonificación aplicada y que contienen las facturas relacionadas. Si el egreso está basado en un pocentaje (como al aplicar un 30% de descuento), dicho porcentaje debe incluirse en la descripción junto al nombre del producto que corresponda. */ + description: string + /** + * Clave de producto/servicio, del catálogo del SAT. Nosotros te proporcionamos una manera más conveniente de encontrarlo utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/productKey). + * @default 84111506 + */ + product_key?: string + /** Suma total de la cantidad devuelta, descontada o bonificada. */ + price: number + /** + * - `true`: Indica que todos los impuestos aplicables están incluidos en el precio (atributo price) y se desglosarán automáticamente al emitir la factura. + * - `false`: Indica que el atributo price no incluye impuestos, por lo que aquellos impuestos a aplicar se sumarán en el precio final. + * @default true + */ + tax_included?: boolean + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * @default 02 + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** + * Lista de impuestos que deberán aplicarse a este producto. + * + * Resolución cuando `taxes` se omite o es `null`: + * - `taxability` omitido o `"02"`: se agrega IVA trasladado 16%. + * - `taxability` en `"01"`, `"03"`, `"04"`, `"05"`, `"06"` o `"08"`: se guarda `[]`. + * - `taxability = "07"`: la solicitud es inválida; debes enviar al menos un IEPS de traslado y no incluir IVA. + * + * Si envías `taxes` explícitamente, se usa el arreglo enviado. + * @default [ + * { + * "type": "IVA", + * "rate": 0.16 + * } + * ] + */ + taxes?: components['schemas']['BaseTax'][] + /** + * Arreglo de impuestos locales (estatales o municipales), en caso de haberlos. + * @default [] + */ + local_taxes?: components['schemas']['LocalTax'][] + /** + * Clave de unidad de medida, del catálogo del SAT. + * Puedes encontrar la clave utilizando nuestra [herramienta de búsqueda de claves](https://dashboard.facturapi.io/catalogs/unit). + * @default ACT + */ + unit_key?: string + /** + * Palabra que representa la unidad de medida de tu producto. Debe estar relacionada con la clave de unidad `unit_key`. + * @default Actividad + */ + unit_name?: string + } + /** Payment */ + PaymentInput: { + /** Código de la forma de pago según el [catálogo del SAT](#forma-de-pago). También puedes utilizar la constante `PaymentForm` incluida en nuestras librerías. */ + payment_form: string + /** Arreglo que incluye un elemento por cada comprobante de ingreso relacionado a este pago. Lo más común es que el pago esté relacionado a un sólo comprobante de ingreso. Un caso en el que se agrega más de un elemento es cuando se recibe (por ejemplo) un sólo depósito que ampara el pago de 2 facturas relacionadas. En lugar de expedir un comprobante de recepción de pago por cada factura, debes expedir sólo uno relacionando los 2 comprobantes. */ + related_documents: { + /** + * Format: uuid + * Folio fiscal ó UUID del comprobante de ingreso relacionado. + */ + uuid: string + /** + * Cantidad del pago correspondiente al comprobante relacionado, + * usando el método de pago indicado en este elemento del arreglo + * de pagos. Este valor debe ser expresado en la moneda definida + * en `related_documents[].currency`. + */ + amount: number + /** Arreglo con impuestos del documento relacionado que aplican al pago realizado. */ + taxes: { + /** Base utilizada para el cálculo del impuestos. */ + base: number + /** + * Tipo de impuesto. + * @enum {string} + */ + type: TaxType + /** Tasa o cuota del impuesto */ + rate: number + /** + * Tipo factor. + * @default Tasa + * @enum {string} + */ + factor?: TaxFactor + /** + * Indica si el impuesto es una retención (`true`) o un traslado (`false`). + * @default false + */ + withholding?: boolean + }[] + /** + * Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo "ObjetoImp" en el CFDI. + * + * - `01`: No objeto de impuesto. + * - `02`: Sí objeto de impuesto. + * - `03`: Sí objeto de impuesto, pero no obligado a desglose. + * - `04`: Sí objeto de impuesto, y no causa impuesto. + * - `05`: Sí objeto de impuesto, IVA crédito PODEBI. + * - `06`: Sí objeto de impuesto, no IVA trasladado. + * - `07`: No traslado de IVA, pero desglose de IEPS. + * - `08`: No traslado de IVA sin desglose de IEPS. + * + * Si se omite, se utiliza `01` cuando `taxes` está vacío y `02` cuando contiene al menos un impuesto. + * @enum {string} + */ + taxability?: '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' + /** Número de parcialidad del pago. */ + installment: number + /** Cantidad que estaba pendiente por pagar antes de recibir este pago. Este valor se expresa en la moneda definida en `related_documents[].currency`. */ + last_balance: number + /** + * Si la moneda utilizada en la factura relacionada no es moneda nacional (MXN), debe especificarse su valor acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** Obligatorio cuando la moneda del documento relacionado es distinta a la moneda de pago. Tipo de cambio entre las dos monedas al momento del pago. Ejemplo: La factura de ingreso relacionada se registra en USD, mientras que el pago actual se realiza en MXN, este atributo debería registrarse como `0.45` (USD/MXN). */ + exchange?: number + /** Opcionalmente se puede incluir el número de folio del documento relacionado. */ + folio_number?: number + /** Opcionalmente se puede incluir la serie del documento relacionado. */ + series?: string | null + }[] + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Format: date-time + * Fecha en que se recibió el pago. Si se omite, se utiliza la fecha y hora actuales. Inclúyela cuando el pago sea anterior a la emisión del comprobante. No se permiten fechas futuras. + */ + date?: Date + /** Número de cheque, de autorización, de referencia, clave de rastreo SPEI, línea de captura o algún número de referencia que permita identificar la operación correspondiente al pago efectuado. */ + numOperacion?: string + /** RFC de la entidad emisora de la cuenta de origen, es decir, la operadora, banco, institución financiera, emisor de monedero electrónico, etc. */ + rfcEmisorCtaOrd?: string + /** Nombre del banco ordenante. */ + nomBancoOrdExt?: string + /** Número de cuenta con la que se realizó el pago. */ + ctaOrdenante?: string + /** RFC de la entidad de la cuenta operadora destino, es decir, la operadora, banco, institución financiera, emisor de monedero electrónico, etc. */ + rfcEmisorCtaBen?: string + /** Número de cuenta donde se recibió el pago. */ + ctaBeneficiario?: string + /** + * Clave del tipo de cadena de pago que genera la entidad receptora del pago. + * Si existe este campo, es obligatorio registrar los campos `certPago`, `cadPago` y `selloPago`. + * @enum {string} + */ + tipoCadPago?: '01' + /** + * Format: base64 + * Certificado que corresponde al pago, como una cadena de texto en formato base 64. + */ + certPago?: string + /** Cadena original del comprobante de pago generado por la entidad emisora de la cuenta beneficiaria. */ + cadPago?: string + /** + * Format: base64 + * Sello digital que se asocie al pago expresado como una cadena de texto en formato base 64. + */ + selloPago?: string + } + /** Objeto con información parcial del cliente receptor del comprobante. Para obtener el objeto `Customer` completo, deberás consultarlo con el método de [Obtener Cliente]('#/operation/getCustomer'). */ + CustomerInfo: { + /** ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado */ + id?: string + /** Nombre Fiscal o Razón Social del cliente, *sin* incluir el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** RFC del cliente. */ + tax_id?: string + address?: { + /** + * Format: ISO 3166-1 alpha-3 + * Código de País acorde al estándar ISO 3166-1 alpha-3, del Catálogo de Países. + */ + country?: string + zip?: string + } + tax_system?: string | null + } + /** Objeto con información parcial del cliente receptor del comprobante. Para obtener el objeto `Customer` completo, deberás consultarlo con el método de [Obtener Cliente]('#/operation/getCustomer'). */ + CustomerComercioExterior: { + /** ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado */ + id?: string + } + RelatedDocumentInput: WithRequired< + components['schemas']['RelatedDocument'], + 'relationship' + > + RelatedDocument: { + /** Clave de relación del catálogo del SAT que puedes consultar en [esta tabla](#relacion-entre-facturas). Es requerido cuando se envíe el parámetro `related_documents`. */ + relationship?: string + /** + * Folios fiscales (UUID) de facturas relacionadas. + * @default [] + */ + documents?: string[] + } + /** + * Status de generación del ZIP: + * - `created`: la solicitud fue creada y programada. + * - `processing`: la generación está en curso. + * - `finished`: el ZIP está listo para descargarse. + * - `failed`: falló la programación o generación. + * - `none`: valor legado; normalmente no se regresa en este flujo. + * @enum {string} + */ + InvoiceZipRequestStatus: + 'created' | 'processing' | 'finished' | 'failed' | 'none' + /** + * Tipo de factura (`I` Ingreso, `E` Egreso, `T` Traslado, `N` Nómina o `P` Pago). + * @enum {string} + */ + InvoiceZipRequestInvoiceType: InvoiceType + InvoiceZipRequestCreateInput: { + year: number + month: number + /** @default issuing */ + issuer_type?: components['schemas']['IssuingType'] + /** Tipos de factura a incluir. Por defecto se incluyen todos. */ + invoice_types?: components['schemas']['InvoiceZipRequestInvoiceType'][] + } + /** Objeto InvoiceZipRequest */ + InvoiceZipRequest: components['schemas']['ResourceAutoGeneratedProps'] & { + /** + * Siempre es `true` para este flujo. + * @constant + */ + livemode?: true + /** Identificador de la organización. */ + organization: string + issuer_type: components['schemas']['IssuingType'] + /** Tipos normalizados de las facturas incluidas. */ + invoice_types: components['schemas']['InvoiceZipRequestInvoiceType'][] + /** + * Format: date-time + * Inicio inclusivo del mes solicitado. + */ + start_date: Date + /** + * Format: date-time + * Fin inclusivo del mes solicitado. + */ + end_date: Date + status: components['schemas']['InvoiceZipRequestStatus'] + /** Número total de facturas por procesar. */ + document_count: number + /** Número de facturas procesadas. */ + processed_document: number + /** Facturas que no pudieron agregarse al ZIP. */ + failed_documents: string[] + /** + * Format: date-time + * Fecha en que se programó el procesamiento. + */ + scheduled_at?: Date + /** + * Format: date-time + * Momento en que comenzó el procesamiento, si existe. + */ + processing_started_at?: Date + } + InvoiceZipRequestSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['InvoiceZipRequest'][] + } + /** Objeto Invoice */ + Invoice: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['InvoiceProperties'] + /** Objeto Invoice con status draft */ + InvoiceDraft: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['InvoiceDraftProperties'] + InvoiceSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Invoice'][] + } + InvoiceRequiredProperties: Record + InvoiceProperties: { + /** + * Estado actual de la factura. `failed` indica que el timbrado en segundo plano o la recuperación automática del CFDI terminó sin éxito. + * @enum {string} + */ + status?: InvoiceStatus + /** + * Estado actual de la solicitud de cancelación, en caso de haberla realizado. Puedes leer más a detalle en la sección de [Cancelar Factura](#tag/invoice/operation/deleteInvoice)). + * @enum {string} + */ + cancellation_status?: CancellationStatus + /** + * Format: date-time + * Fecha en la que se canceló el CFDI con hora aproximada. + */ + canceled_at?: Date | null + /** + * Format: uri + * Dirección URL para verificar el estado del CFDI en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la factura. + */ + verification_url?: string + /** + * Format: date-time + * Fecha de expedición en formato ISO8601. Puede ser null en borradores. + */ + date: Date | null + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + * @enum {string} + */ + type?: InvoiceType + customer?: components['schemas']['CustomerInfo'] | null + /** Monto total facturado. */ + total?: number + /** + * Format: uuid + * Folio fiscal de la factura, asignado por el SAT. + */ + uuid?: string + /** Número de folio autoincremental para control interno y sin validez fiscal. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. En el PDF se imprime junto al número de folio. */ + series?: string + /** Identificador que puedes usar para relacionar esta factura con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Total del complemento de Pago cuando la factura es tipo P. */ + total_payment_amount?: number + /** Total del monto pagado convertido de la moneda de pago a Pesos Mexicanos. */ + total_payment_amount_converted?: number + /** + * Este campo es asignado automáticamente por Facturapi. Indica si una factura + * con status `draft` está completa y lista para intentar timbrarse. Si el valor es `true`, puedes + * intentar timbrar la factura con el método [Timbrar Factura]('#/operation/stampInvoice'). + * Si el valor es `false`, debes usar el método [Actualizar Factura]('#/operation/updateDraftInvoice') + * para completar los campos faltantes. + * + * En una factura con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + /** Conceptos incluidos en el comprobante */ + items?: components['schemas']['LineItem'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocument'][] + /** + * En facturas con tipo I (Ingreso) y método de pago PPD, este campo lista los + * IDs de los comprobantes de pago cuyo arreglo de documentos relacionados incluye el UUID + * de esta factura. Este campo es llenado por Facturapi en el momento en que se crea o importa + * el comprobante de pago (tipo P), siempre y cuando pertenezca a la misma organización. + * @default [] + */ + received_payment_ids?: string[] + /** + * En facturas con tipo P (Pago), este arreglo lista los IDs de los comprobantes de ingreso + * listados en el arreglo de documentos relacionados. Este campo es llenado por Facturapi siempre + * y cuando el comprobante relacionado también esté registrado en Facturapi y pertenezca a la misma organización. + * @default [] + */ + target_invoice_ids?: string[] + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en la factura. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementProperties'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + stamp?: components['schemas']['Stamp'] | null + /** ID de la organización a la que pertenece este recurso. */ + organization?: string | null + issuer_type?: components['schemas']['IssuingType'] + cfdi_version?: number + issuer_info?: components['schemas']['CustomerInfo'] + /** @enum {string} */ + payment_method?: PaymentMethod + use?: string + amount_due?: number + /** Format: uri */ + verification_carta_porte?: string + conditions?: string + export?: string + global?: { + /** @enum {string} */ + periodicity: GlobalInvoicePeriodicity + months: string + year: number + } + } + InvoiceDraftProperties: { + /** + * Estado actual de la factura. + * @enum {string} + */ + status?: 'pending' | 'valid' | 'canceled' | 'draft' + /** + * Estado actual de la solicitud de cancelación, en caso de haberla realizado. Puedes leer más a detalle en la sección de [Cancelar Factura](#tag/invoice/operation/deleteInvoice)). + * @enum {string} + */ + cancellation_status?: CancellationStatus + /** + * Format: uri + * Dirección URL para verificar el estado del CFDI en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la factura. + */ + verification_url?: string + /** + * Format: date-time + * Fecha de timbrado del comprobante en formato ISO8601 (UTC String). Si el estado es `draft`, este campo es nulo. + */ + date?: Date | null + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + * @enum {string} + */ + type?: InvoiceType + /** Cliente de la factura. Es null cuando el borrador no tiene cliente. */ + customer?: components['schemas']['CustomerInfo'] | null + /** Monto total facturado. */ + total?: number + /** + * Format: uuid + * Folio fiscal asignado por el SAT. En un borrador sin timbrar, este campo es null o se omite. + */ + uuid?: string | null + /** Número de folio autoincremental para control interno y sin validez fiscal. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. En el PDF se imprime junto al número de folio. */ + series?: string + /** Identificador que puedes usar para relacionar esta factura con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Conceptos incluidos en el comprobante */ + items?: components['schemas']['LineItem'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocument'][] + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en la factura. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementProperties'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + /** + * Este campo es asignado automáticamente por Facturapi. Indica si una factura + * con status `draft` está completa y lista para intentar timbrarse. Si el valor es `true`, puedes + * intentar timbrar la factura con el método [Timbrar Factura]('#/operation/stampInvoice'). + * Si el valor es `false`, debes usar el método [Actualizar Factura]('#/operation/updateDraftInvoice') + * para completar los campos faltantes. + * + * En una factura con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + stamp?: components['schemas']['Stamp'] | null + } + InvoiceableCommonInput: { + /** Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** + * Format: xml + * En caso de que necesites incluir más información en el PDF, este campo te permite enviar código HTML con tu propio contenido. + * + * Por seguridad, el código que puedes enviar está limitado a las siguientes etiquetas: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `div`, `p`, `span`, `small`, `br`, `b`, `i`, `ul`, `ol`, `li`, `strong`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th` y `td`. No se permiten atributos ni estilos. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** + * Si incluiste el parámetro `complements`, este campo es opcional; en cambio si incluiste el parámetro `addenda`, debes enviar la información necesaria para incluir estos namespaces en el documento XML. + * @default [] + */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia del cliente para la factura en curso. Utiliza este campo para peticiones de generación de facturas en las cuales necesites utilizar una configuración distinta al campo pdf_extra de la organización. */ + pdf_options?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostrarán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + InvoiceableCommonEditInput: { + /** Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** + * Format: xml + * En caso de que necesites incluir más información en el PDF, este campo te permite enviar código HTML con tu propio contenido. + * + * Por seguridad, el código que puedes enviar está limitado a las siguientes etiquetas: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `div`, `p`, `span`, `small`, `br`, `b`, `i`, `ul`, `ol`, `li`, `strong`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th` y `td`. No se permiten atributos ni estilos. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Si incluiste el parámetro `complements`, este campo es opcional; en cambio si incluiste el parámetro `addenda`, debes enviar la información necesaria para incluir estos namespaces en el documento XML. */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia del cliente para la factura en curso. Utiliza este campo para peticiones de generación de facturas en las cuales necesites utilizar una configuración distinta al campo pdf_extra de la organización. */ + pdf_options?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + /** Cliente receptor de la factura. */ + InvoiceCustomerInput: components['schemas']['CustomerCreateInput'] | string + InvoiceCommonInputProperties: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Estado inicial de la factura. Si se envía `draft`, la factura se guardará como borrador y no se timbrará ni se + * enviará al SAT. También al enviar `draft`, todos los campos requeridos se vuelven + * opcionales. Si se omite, el estado por default es `pending` y una vez timbrada (en la respuesta) este + * campo se actualizará a `valid`. Para facturas asíncronas, este campo se quedará en `pending` hasta que + * se timbre la factura. + * @default pending + * @enum {string} + */ + status?: 'pending' | 'draft' + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601. Si se omite, se utiliza la fecha y hora actuales. No puede ser anterior a 72 horas en el pasado ni posterior al presente. + */ + date?: Date + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** Identificador opcional que puedes usar para relacionar esta factura con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } & components['schemas']['InvoiceableCommonInput'] + InvoiceCommonEditInputProperties: { + /** + * Estado de la factura. El valor `draft` identifica un borrador que no se ha timbrado ni enviado al SAT. + * Sólo es posible editar facturas con este estado; al editarlas, no se puede cambiar `status`. + * @enum {string} + */ + status?: 'draft' + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). No puede ser anterior a 72 horas en el pasado, ni posterior al presente. + */ + date?: Date + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** Identificador opcional que puedes usar para relacionar esta factura con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } & components['schemas']['InvoiceableCommonEditInput'] + InvoiceDraftInputProperties: components['schemas']['InvoiceCommonEditInputProperties'] & { + /** Cliente receptor de la factura. */ + customer?: null | components['schemas']['CustomerCreateInput'] | string + } + /** Datos de la factura según su tipo y estado inicial. Omite status para timbrar; usa draft para guardar un borrador. */ + InvoiceCreateInput: + | ( + | (components['schemas']['InvoiceIngresoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceIngresoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceEgresoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceEgresoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoicePagoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoicePagoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceNominaInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceNominaEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + | ( + | (components['schemas']['InvoiceTrasladoInput'] & { + /** + * @default pending + * @constant + */ + status?: 'pending' + }) + | (components['schemas']['InvoiceTrasladoEditInput'] & { + /** @constant */ + status: 'draft' + }) + ) + /** Ingreso */ + InvoiceIngresoInput: { + /** + * Tipo de comprobante. El valor default es `“I”` (Ingreso). + * @default I + * @enum {string} + */ + type?: 'I' + /** + * Conceptos a incluir en la factura. + * + * El número máximo de elementos que puedes incluir en una factura es de 5,000. Si necesitas + * emitir una factura con más de 5,000 conceptos, puedes dividir la transacción en varias facturas. + */ + items: components['schemas']['LineItemInput'][] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form: string + /** + * Código del método de pago según el catálogo del SAT. + * + * - `PUE`: Pago en Una sola Exhibición + * - `PPD`: Pago en Parcialidades o Diferido + * @default PUE + * @enum {string} + */ + payment_method?: PaymentMethod + /** + * Si se omite o es null, se utiliza el uso configurado en el cliente; si no tiene uno, se utiliza G03. Para clientes extranjeros o público en general se utiliza S01. + * + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos + * en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en + * nuestras librerías. + * + * Para factura global debe ingresarse la clave `S01`. + */ + use?: string | null + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos + * mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** Condiciones de pago */ + conditions?: string + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** Objeto requerido al crear una factura global. */ + global?: { + /** + * Periodicidad que abarca la factura global. + * + * - `day`: Diario + * - `week`: Semanal + * - `fortnight`: Quincenal + * - `month`: Mensual + * - `two_months`: Bimestral + * @enum {string} + */ + periodicity: GlobalInvoicePeriodicity + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + */ + months: string + /** Año de la factura. */ + year: number + } + /** + * Indica si el comprobante ampara una operación de exportación. + * + * - `01`: No aplica + * - `02`: Definitiva con clave A1 + * - `03`: Temporal + * - `04`: Definitiva con clave distinta a A1 o cuando no existe enajenación en términos del CFF + * @default 01 + * @enum {string} + */ + export?: '01' | '02' | '03' | '04' + /** + * Complementos a incluir en la factura. Puedes incluir cualquier complemento en la + * factura si tú mismo construyes el nodo XML del complemento y usas el tipo `custom`. + * Es necesario agregar la información del complemento al PDF por separado usando el + * parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Egreso */ + InvoiceEgresoInput: { + /** @enum {string} */ + type: 'E' + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form: string + /** + * Código del método de pago según el catálogo del SAT. Para facturas de Egreso, + * este campo es opcional y el único valor permitido es `PUE` (Pago en Una sola Exhibición). + * @default PUE + * @enum {string} + */ + payment_method?: 'PUE' + /** + * Documentos relacionados con la nota de crédito. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** + * Conceptos a incluir en la nota de crédito. + * + * El número máximo de elementos que puedes incluir en el comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items: components['schemas']['LineItemEgresoInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default G02 + */ + use?: string + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default MXN + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier + * complemento en el comprobante si tú mismo construyes el nodo XML del + * complemento y usas el tipo `custom`. Es necesario agregar la información + * del complemento al PDF por separado usando el parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Pago */ + InvoicePagoInput: { + /** @enum {string} */ + type: 'P' + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Complementos a incluir en la factura. */ + complements: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Nómina */ + InvoiceNominaInput: { + /** @enum {string} */ + type: 'N' + /** Complementos a incluir en la factura. */ + complements: components['schemas']['InvoiceComplementInput'][] + /** + * Documentos relacionados con la factura. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Traslado */ + InvoiceTrasladoInput: { + /** @enum {string} */ + type: 'T' + /** + * Conceptos a incluir en el comprobante de Traslado. + * + * El número máximo de elementos que puedes incluir en un comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items: components['schemas']['LineItemTrasladoInput'][] + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier complemento en + * el comprobante si tú mismo construyes el nodo XML del complemento y usas el tipo + * `custom`. Es necesario agregar la información del complemento al PDF por separado + * usando el parámetro `pdf_custom_section`. + * @default [] + */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en + * [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default S01 + */ + use?: string + /** + * Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). + * @default XXX + */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos + * (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + * @default 1 + */ + exchange?: number + /** + * Documentos relacionados con el comprobante. + * @default [] + */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonInputProperties'] + /** Ingreso */ + InvoiceIngresoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'I' + /** + * Conceptos a incluir en la factura. + * + * El número máximo de elementos que puedes incluir en una factura es de 5,000. Si necesitas + * emitir una factura con más de 5,000 conceptos, puedes dividir la transacción en varias facturas. + */ + items?: components['schemas']['LineItemInput'][] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string | null + /** + * Código del método de pago según el catálogo del SAT. + * + * - `PUE`: Pago en Una sola Exhibición + * - `PPD`: Pago en Parcialidades o Diferido + * @enum {string} + */ + payment_method?: PaymentMethod + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos + * en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en + * nuestras librerías. + * + * Para factura global debe ingresarse la clave `S01`. + */ + use?: string | null + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos + * mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + */ + exchange?: number + /** Condiciones de pago */ + conditions?: string + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** Objeto requerido al crear una factura global. */ + global?: { + /** + * Periodicidad que abarca la factura global. + * + * - `day`: Diario + * - `week`: Semanal + * - `fortnight`: Quincenal + * - `month`: Mensual + * - `two_months`: Bimestral + * @enum {string} + */ + periodicity: GlobalInvoicePeriodicity + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + */ + months: string + /** Año de la factura. */ + year: number + } + /** + * Indica si el comprobante ampara una operación de exportación. + * + * - `01`: No aplica + * - `02`: Definitiva con clave A1 + * - `03`: Temporal + * - `04`: Definitiva con clave distinta a A1 o cuando no existe enajenación en términos del CFF + * @enum {string} + */ + export?: '01' | '02' | '03' | '04' + /** + * Complementos a incluir en la factura. Puedes incluir cualquier complemento en la + * factura si tú mismo construyes el nodo XML del complemento y usas el tipo `custom`. + * Es necesario agregar la información del complemento al PDF por separado usando el + * parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Egreso */ + InvoiceEgresoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'E' + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** + * Código del método de pago según el catálogo del SAT. Para facturas de Egreso, + * este campo es opcional y el único valor permitido es `PUE` (Pago en Una sola Exhibición). + * @enum {string} + */ + payment_method?: 'PUE' + /** Documentos relacionados con la nota de crédito. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + /** + * Conceptos a incluir en la nota de crédito. + * + * El número máximo de elementos que puedes incluir en el comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items?: components['schemas']['LineItemEgresoInput'][] + /** Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. */ + use?: string + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier + * complemento en el comprobante si tú mismo construyes el nodo XML del + * complemento y usas el tipo `custom`. Es necesario agregar la información + * del complemento al PDF por separado usando el parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Pago */ + InvoicePagoEditInput: { + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'P' + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + third_party?: Record & + components['schemas']['ThirdParty'] + /** Complementos a incluir en la factura. */ + complements?: components['schemas']['InvoiceComplementInput'][] + } & components['schemas']['InvoiceDraftInputProperties'] + /** Nómina */ + InvoiceNominaEditInput: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'N' + /** Complementos a incluir en la factura. */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** Documentos relacionados con la factura. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonEditInputProperties'] + /** Traslado */ + InvoiceTrasladoEditInput: { + customer?: components['schemas']['InvoiceCustomerInput'] + /** + * Tipo de comprobante de esta variante de entrada. + * @constant + */ + type?: 'T' + /** + * Conceptos a incluir en el comprobante de Traslado. + * + * El número máximo de elementos que puedes incluir en un comprobante es de 5,000. Si necesitas + * emitir un comprobante con más de 5,000 conceptos, puedes dividir la transacción en varios comprobantes. + */ + items?: components['schemas']['LineItemTrasladoInput'][] + /** + * Complementos a incluir en el comprobante. Puedes incluir cualquier complemento en + * el comprobante si tú mismo construyes el nodo XML del complemento y usas el tipo + * `custom`. Es necesario agregar la información del complemento al PDF por separado + * usando el parámetro `pdf_custom_section`. + */ + complements?: components['schemas']['InvoiceComplementInput'][] + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en + * [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + */ + use?: string + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** + * Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos + * (MXN) que equivalen a una unidad de la divisa señalada en el atributo `currency`. + */ + exchange?: number + /** Documentos relacionados con el comprobante. */ + related_documents?: components['schemas']['RelatedDocumentInput'][] + } & components['schemas']['InvoiceCommonEditInputProperties'] + /** Objeto Receipt */ + Receipt: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['ReceiptProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + } + ReceiptProperties: { + /** + * Format: date-time + * Fecha de emisión del recibo. + */ + date: Date + /** + * Format: date-time + * Fecha de expiración en formato ISO8601 (UTC String). + * Es la fecha límite para que el cliente pueda facturar su recibo en el portal de autofactura. + * Se calcula automáticamente a partir de las configuraciones de recibo de la organización. + */ + expires_at: Date + /** + * Estado actual del recibo. + * @enum {string} + */ + status?: ReceiptStatus + /** + * Format: url + * Dirección URL para realizar autofactura. Incluye el `key` del recibo. + * Puedes usarla para generar un botón o un QR de facturación para tus clientes. + */ + self_invoice_url?: string + /** Monto total de la operación */ + total?: number + /** ID de la factura asociada, en caso de estar facturado. */ + invoice?: string + /** ID del cliente asociado al recibo, en caso de haberse asignado. */ + customer?: string + /** Autogenerado. Identificador único alfanumérico corto, útil para acceder a la autofactura desde tu micrositio en factura.space */ + key?: string + /** Conceptos incluidos en el recibo */ + items?: components['schemas']['LineItem'][] + /** Identificador que puedes usar para relacionar este recibo con tus registros para después buscar por este número. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + } & components['schemas']['ReceiptEditableProperties'] + ReceiptInput: { + /** Cliente asociado al recibo. Puedes enviar el ID de un cliente existente o un objeto de cliente para crearlo. */ + customer?: string | components['schemas']['CustomerCreateInput'] + address?: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + /** + * Conceptos a incluir en el recibo. + * + * El número máximo de elementos que puedes incluir en un recibo es de 5,000. Si necesitas + * emitir una recibo con más de 5,000 conceptos, prueba dividir la transacción en varios recibos. + */ + items: components['schemas']['LineItemInput'][] + } & components['schemas']['ReceiptEditableProperties'] & { + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + } + ReceiptEditableProperties: { + /** + * Format: date-time + * Fecha de emisión del recibo. Por defecto se utiliza la fecha actual. + */ + date?: Date + /** Código que representa la forma de pago, según el [catálogo del SAT](#forma-de-pago). */ + payment_form?: string + /** Autoincremental. Número de folio del recibo para control interno y sin validez fiscal. */ + folio_number?: number + /** Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). */ + currency?: string + /** Tipo de cambio conforme a la moneda usada. Representa el número de pesos mexicanos que equivalen a una unidad de la divisa señalada en el atributo `currency`. */ + exchange?: number + /** Nombre de la sucursal donde se expidió el recibo. */ + branch?: string + /** Identificador opcional que puedes usar para relacionar este recibo con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + } + ReceiptAssignCustomerInput: { + /** Cliente a asignar o reasignar al recibo. Puedes enviar el ID de un cliente existente o un objeto de cliente para crearlo. */ + customer: string | components['schemas']['CustomerCreateInput'] + } + ReceiptSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Receipt'][] + } + InvoiceReceiptInput: { + /** + * Cliente receptor de la factura. Puedes enviarlo como ID de un cliente existente + * o como objeto para crear un cliente nuevo. Si lo omites, el recibo debe tener + * un cliente asignado previamente. + */ + customer?: components['schemas']['CustomerCreateInput'] | string + /** + * Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos en [esta tabla](#uso-cfdi), o utilizar las constantes incluidas en nuestras librerías. + * @default G01 + */ + use?: string + /** Condiciones de pago */ + conditions?: string + } & components['schemas']['InvoiceableCommonInput'] + /** Las fechas son opcionales al seleccionar por periodo. Al enviar receipts se requieren from y to. La periodicidad predeterminada viene de la configuración de la organización. */ + GlobalInvoiceInput: + | (components['schemas']['GlobalInvoiceInputProperties'] & { + receipts?: never + }) + | WithRequired< + components['schemas']['GlobalInvoiceInputProperties'], + 'receipts' | 'from' | 'to' + > + GlobalInvoiceInputProperties: { + /** + * Fecha inicial de los recibos que se incluirán en la factura global. + * Por default, este valor es el inicio del último periodo (día, semana, + * quincena o mes), según el valor de "Periodicidad" (`periodicity`) + * en la configuración de recibos de tu organización. Este valor es requerido cuando se envíe el campo `receipts`. + */ + from?: components['schemas']['DateOrDateTime'] + /** + * Fecha final de los recibos que se incluirán en la factura global. + * Por default, este valor es el fin del último periodo (día, semana, + * quincena o mes), según el valor de "Periodicidad" (`periodicity`) + * en la configuración de recibos de tu organización. Este valor es requerido cuando se envíe el campo `receipts`. + */ + to?: components['schemas']['DateOrDateTime'] + /** + * Periodicidad que corresponde al rango de fechas utilizado. + * Si omites los campos `from` y `to`, las fechas que se asignarán por + * default dependerán del valor de `periodicity`. + * + * Si se omite, se utiliza la periodicidad configurada en los recibos de la organización. + * @enum {string} + */ + periodicity?: GlobalInvoicePeriodicity + /** + * Clave que representa el mes o bimestre de la factura. Consulta + * los posibles valores en el [catálogo de Meses y Bimestres](#meses-y-bimestres). + * + * Si se omite, el mes o bimestre se determina a partir de la fecha inicial y la periodicidad. + */ + months?: string + /** + * Número de folio asignado por la empresa para control interno. + * Si se omite, se asignará el valor autoincremental de la organización. + */ + folio_number?: number + /** Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. */ + series?: string + /** Fecha de emisión de la factura. Si se omite, se utiliza la fecha final (`to`), limitada a la fecha y hora actuales. */ + date?: components['schemas']['DateOrDateTime'] + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). Si se incluye, los recibos se agruparán y se crearán la factura global por la forma de pago. */ + payment_form?: string + /** Recibos a incluir en la factura global. Si se incluye este parámetro, los parámetros `from` y `to` serán requeridos y tendrán que cumplir con el campo `periodicity`. */ + receipts?: string[] + /** + * Permite procesar periodos con más de 5,000 recibos abiertos. Cuando es + * `true`, la factura incluye como máximo 5,000 recibos y los restantes + * conservan el status `"open"`. Repite la solicitud con el mismo periodo + * hasta recibir `null`, que indica que ya no quedan recibos por facturar. + * + * Cuando es `false`, un periodo con más de 5,000 recibos abiertos devuelve + * el error `global_invoice_too_many_items`. + * @default false + */ + limit_to_max_receipts?: boolean + } + ToInvoiceInput: { + /** Lista de keys de recibos que se incluirán en la factura. */ + keys: string[] + /** + * Cliente receptor de la factura. Si lo envías, sobrescribe el cliente + * asignado a los recibos incluidos. Si lo omites, todos los recibos deben + * tener asignado el mismo cliente. Esta regla también aplica cuando + * `dry_run` es `true`. + */ + customer?: components['schemas']['CustomerCreateInput'] | string + /** + * Código de Uso CFDI según catálogo del SAT. + * @default G01 + */ + use?: string + /** + * Si es `true`, sólo valida y regresa un resumen sin crear la factura. + * @default false + */ + dry_run?: boolean + /** Código de forma de pago según el [catálogo del SAT](#forma-de-pago). */ + payment_form?: string | null + } + ToInvoicePreviewInput: { + /** Lista de keys de recibos que se incluirán en la vista previa. */ + keys: string[] + /** + * Cliente opcional para renderizar la vista previa. Si lo omites, + * todos los recibos deben tener asignado el mismo cliente. + */ + customer?: components['schemas']['CustomerCreateInput'] | string | null + /** + * Código de Uso CFDI según catálogo del SAT. + * @default G01 + */ + use?: string + } + /** Resumen de importes e impuestos de los recibos cuando `dry_run=true`. */ + ToInvoiceSummary: { + subtotal: number + discount: number + total: number + receipts: string[] + payment_form: string + item_count: number + taxes: { + totalAdded: number + totalWithholding: number + localTotalAdded: number + localTotalWithholding: number + allAdded: components['schemas']['ReceiptInvoiceSummaryTax'][] + allWithholding: components['schemas']['ReceiptInvoiceSummaryTax'][] + localAllAdded: components['schemas']['ReceiptInvoiceSummaryTax'][] + localAllWithholding: components['schemas']['ReceiptInvoiceSummaryTax'][] + } + } + ReceiptInvoiceSummaryTax: { + type?: string + rate?: number + /** @enum {string} */ + factor: TaxFactor + withholding: boolean + base: number + amount: number + name?: string + } & { + [key: string]: unknown + } + /** Objeto Retention */ + Retention: components['schemas']['ResourceAutoGeneratedProps'] & + components['schemas']['RetentionReadOnlyProperties'] & + components['schemas']['RetentionProperties'] & { + /** ID de la organización a la que pertenece este recurso. */ + organization?: string + } + RetentionReadOnlyProperties: { + /** + * Estado actual de la retención. + * @enum {string} + */ + status?: 'draft' | 'pending' | 'valid' | 'canceled' + /** + * Format: uri + * Dirección URL para verificar el estado de la retención en el portal del SAT. Este link es el mismo que aparece en el código QR, en el PDF de la retención. + */ + verification_url?: string + /** + * Tipo de comprobante. + * @enum {string} + */ + type?: 'Retención' + /** + * Format: uuid + * Folio fiscal de la retención, asignado por el SAT. + */ + uuid?: string + stamp?: components['schemas']['Stamp'] | null + customer?: components['schemas']['CustomerInfo'] | null + /** + * Indica si la retención con status `draft` está completa y lista para intentar timbrarse. + * En una retención con status diferente a `draft`, este campo siempre será `false`. + */ + is_ready_to_stamp?: boolean + } + RetentionProperties: { + /** Clave de la retención o información de pagos de acuerdo al catálogo del SAT. */ + cve_retenc?: string + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). + */ + fecha_exp: Date | null + /** Si la clave de la retención es “25” (Otro tipo de retenciones), este campo se usa para registrar la descripción de la retención. */ + desc_retenc?: string + /** Identificador alfanumérico para control interno de la empresa y sin relevancia fiscal. */ + folio_int?: string + /** Información sobre el periodo de la retención. */ + periodo?: { + /** Mes inicial del periodo de la retención. */ + mes_ini?: number + /** Mes final del periodo de la retención. */ + mes_fin?: number + /** Año o ejercicio fiscal en que se realizó la retención. */ + ejerc?: number + } + /** Información sobre el total de retenciones efectuadas en el periodo correspondiente. */ + totales?: { + /** Monto total de la operación, con precisión de hasta 6 decimales. */ + monto_tot_operacion?: number + /** Monto total gravado. */ + monto_tot_grav?: number + /** Monto total exento. */ + monto_tot_exent?: number + /** Suma de los montos de impuestos retenidos. */ + monto_tot_ret?: number + /** Colección de impuestos retenidos. */ + imp_retenidos?: { + /** Base del impuesto retenido. */ + base?: number + /** + * Clave del tipo de impuesto retenido, del catálogo del SAT. + * @enum {string} + */ + impuesto?: 'IVA' | 'ISR' + /** Importe del impuesto retenido */ + monto?: number + /** + * - `01`: Pago definitivo IVA + * - `02`: Pago definitivo IEPS + * - `03`: Pago definitivo ISR Plataformas + * - `04`: Pago provisional ISR + * @enum {string} + */ + tipo_pago_ret?: '01' | '02' | '03' | '04' + }[] + } + /** Identificador opcional que puedes usar para relacionar esta retención con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** + * Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. + * Si se deja en blanco, no se tomará en cuenta. + */ + idempotency_key?: string + /** + * Arreglo de complementos a incluir en la factura. Cada elemento contiene + * un `string` con el código XML del complemento. + * @default [] + */ + complements?: components['schemas']['CustomComplementData'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: components['schemas']['NamespaceProperties'][] + } + RetentionSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Retention'][] + } + RetentionInput: + | (components['schemas']['RetentionUpdateInput'] & + Record) + | (components['schemas']['RetentionUpdateInput'] & + Record) + RetentionUpdateInput: { + /** + * Estado inicial de la retención. Si se envía `draft`, la retención se + * guardará como borrador y no se timbrará ni se enviará al SAT. También + * al enviar `draft`, `customer`, `cve_retenc`, `periodo` y `totales` + * pueden omitirse o enviarse como `null`. + * @enum {string} + */ + status?: 'draft' + /** Cliente receptor de la factura. */ + customer?: components['schemas']['CustomerCreateInput'] | string | null + /** Clave de la retención o información de pagos de acuerdo al [catálogo del SAT](#clave-de-retencion). */ + cve_retenc?: string | null + /** + * Format: date-time + * Fecha de expedición del comprobante en formato ISO8601 (UTC String). + */ + fecha_exp?: Date + /** Si la clave de la retención es “25” (Otro tipo de retenciones), este campo se usa para registrar la descripción de la retención. */ + desc_retenc?: string + /** Identificador alfanumérico para control interno de la empresa y sin relevancia fiscal. */ + folio_int?: string + /** Información sobre el periodo de la retención. */ + periodo?: { + /** Mes inicial del periodo de la retención. */ + mes_ini: number + /** Mes final del periodo de la retención. */ + mes_fin: number + /** Año o ejercicio fiscal en que se realizó la retención. */ + ejerc: number + } | null + /** Información sobre el total de retenciones efectuadas en el periodo correspondiente. */ + totales?: { + /** Monto total de la operación, con precisión de hasta 6 decimales. */ + monto_tot_operacion: number + /** Monto total gravado. */ + monto_tot_grav?: number + /** Monto total exento. */ + monto_tot_exent: number + /** Suma de los montos de impuestos retenidos. */ + monto_tot_ret?: number + /** Colección de impuestos retenidos. */ + imp_retenidos: { + /** Base del impuesto retenido. */ + base_ret?: number + /** + * Clave del tipo de impuesto retenido, del catálogo del SAT. + * @enum {string} + */ + impuesto?: 'IVA' | 'ISR' + /** Importe del impuesto retenido */ + monto_ret: number + /** + * - `01`: Pago definitivo IVA + * - `02`: Pago definitivo IEPS + * - `03`: Pago definitivo ISR Plataformas + * - `04`: Pago provisional ISR + * @enum {string} + */ + tipo_pago_ret: '01' | '02' | '03' | '04' + }[] + } | null + /** Identificador opcional que puedes usar para relacionar esta retención con tus registros y poder hacer búsquedas usando este identificador. Facturapi no valida que este campo sea único. */ + external_id?: string + /** Identificador único que puedes usar para evitar duplicados al reintentar una petición. Puede ser cualquier cadena de texto, mientras sea única para cada documento. */ + idempotency_key?: string + /** + * Arreglo de complementos a incluir en la factura. Cada elemento del arreglo deberá contener + * un `string` con el código XML de tu complemento tal cual como quieres que se inserte en el + * XML del CFDI. Sólo se permite un nodo XML raíz por elemento del arreglo. + * @default [] + */ + complements?: components['schemas']['CustomComplementData'][] + /** + * Format: html + * En caso de que necesites incluir más información en el PDF, este campo te permite insertar código HTML con tu propio contenido. + */ + pdf_custom_section?: string + /** + * Format: xml + * Código XML con la Addenda que se necesite agregar a la factura. + */ + addenda?: string + /** Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. */ + namespaces?: (components['schemas']['NamespaceRequiredProperties'] & + components['schemas']['NamespaceProperties'])[] + } + OrganizationAddress: components['schemas']['CommonAddressProperties'] & { + /** Nombre del Estado o Entidad Federativa. */ + state?: string + } + OrganizationSearchResult: components['schemas']['SearchResult'] & { + data: components['schemas']['Organization'][] + } + /** Objeto Organization */ + Organization: { + /** ID del objeto */ + id: string + /** + * Format: uri + * URL del logotipo de la organización. + */ + logo_url?: string + /** Zona horaria de la organización, en formato IANA. */ + timezone?: string + /** + * Format: date-time + * Fecha de registro + */ + created_at: Date + /** Indica si la organización tiene información necesaria para facturar en ambiente Live. */ + is_production_ready?: boolean + /** Lista de pasos que se necesitan completar para que esta organización pueda emitir facturas válidas en ambiente Live. */ + pending_steps?: { + /** + * Código que representa el tipo de paso que se requiere completar + * @enum {string} + */ + type?: 'legal' | 'logo' | 'certificate' | 'manifiesto' + /** Texto que describe el paso que se requiere completar y que puedes usar para mostrárselo al usuario. */ + description?: string + }[] + /** Datos fiscales de la empresa. */ + legal?: { + /** Nombre comercial de la organización. */ + name?: string + /** Nombre Fiscal o Razón Social de la organización, *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name?: string + /** Código de Régimen Fiscal, del [catálogo del SAT](#régimen-fiscal). */ + tax_system?: string + /** Sitio web de la organización, que se utilizará al enviar la factura por correo electrónico. */ + website?: string + /** Teléfono de la organización, que aparecerá en el PDF de la factura. */ + phone?: string + address?: Record & + components['schemas']['OrganizationAddress'] + } + /** + * Configuración de personalización de la organización, que se utilizarán para reflejar el branding y + * las preferencias de PDFs de la organización. Estos datos se pueden actualizar en cualquier momento. + */ + customization?: { + /** Indica si la organización ya tiene un logotipo cargado. */ + has_logo?: boolean + /** + * Format: hex + * Color distintivo de la marca en representación Hexadecimal RGB de 6 caracteres. + */ + color?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number_test?: number + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia de la organización. */ + pdf_extra?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. Ejemplo: "SON" en lugar de "Sonora" y "MEX" en lugar de "México". + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. Si se desactiva, la firma electrónica sólo se mostrará una vez. + * @default false + */ + repeat_signature?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + /** Información útil sobre el certificado de sello digital (CSD) de la organización, que se utilizará para firmar las facturas. */ + certificate: { + /** Indica si la organización ya tiene el Certificado de Sello Digital (CSD) cargado. */ + has_certificate?: boolean + /** + * Format: date-time + * Fecha de la última actualización del certificado. Se omite cuando no hay un certificado cargado. + */ + updated_at?: Date + /** + * Format: date-time + * Fecha de expiración del certificado. Se omite cuando no hay un certificado cargado. + */ + expires_at?: Date + /** Número de serie del certificado CSD. */ + serial_number?: string + } + /** Información sobre el certificado FIEL de la organización, que se utiliza para el servicio de descarga masiva de CFDI. */ + fiel: { + /** Indica si la organización ya tiene el Certificado FIEL cargado. */ + has_certificate?: boolean + /** + * Format: date-time + * Fecha de la última actualización del certificado FIEL. Se omite cuando no hay un certificado cargado. + */ + updated_at?: Date + /** + * Format: date-time + * Fecha de expiración del certificado FIEL. Se omite cuando no hay un certificado cargado. + */ + expires_at?: Date + /** Número de serie del certificado FIEL. */ + serial_number?: string + } + /** Configuración para recibos y la emisión de facturas globales a partir de recibos. */ + receipts?: { + /** + * Periodicidad con la que la empresa decide emitir una factura global + * (al público en general) por todos los recibos que no se hayan facturado. + * Este valor se utiliza como el default al crear una factura global. + * @default month + * @enum {string} + */ + periodicity?: InvoicingPeriod + /** + * Número máximo de días para facturar a través del portal de autofactura + * después de que se emite el recibo y antes del último día del periodo. + * @default 7 + */ + duration_days?: number + /** + * Número de folio que se asignará al siguiente recibo en ambiente Live. + * Se incrementará automáticamente por cada nuevo recibo. + */ + next_folio_number?: number + /** + * Número de folio que se asignará al siguiente recibo en ambiente Test. + * Se incrementará automáticamente por cada nuevo recibo. + */ + next_folio_number_test?: number + /** + * Indica si la organización genera automáticamente una factura global + * después de cerrar cada periodo configurado. Requiere tener contratado + * el feature de factura global. + * @default false + */ + activate_global_invoice?: boolean + /** + * Agrupa conceptos equivalentes al facturar varios recibos seleccionados, + * incluyendo las autofacturas. No modifica la generación de facturas globales. + * @default false + */ + grouped_items_invoice?: boolean + } + /** Configuraciones para el portal de autofactura, que permite a los clientes facturar sus recibos a través de un micrositio. */ + self_invoice?: { + /** Lista de usos CFDI permitidos para la autofactura. Si este campo está vacío, se permitirán todos los usos CFDI. */ + allowed_cfdi_uses?: string[] + /** + * Indica si la organización aplica el ISR bajo el régimen RESICO. Si es verdadero, el ISR se calculará de acuerdo con el régimen RESICO. + * Si es falso, el ISR se calculará de acuerdo con el régimen general. + */ + apply_resico_isr?: boolean + /** Dirección de correo electrónico para aclaraciones. Aparecerá en el portal de autofacturación. */ + support_email?: string + /** Indica si el correo electrónico de soporte ha sido verificado. Si es falso, el correo electrónico utilizado en el portal de autofacturación será el correo electrónico principal de la cuenta. */ + support_email_verified?: boolean + } + /** + * @deprecated + * Plan heredado de la organización. + */ + plan?: string | null + /** Funcionalidades adicionales contratadas por la organización. */ + add_ons?: string[] + /** Cambio de plan programado, si existe. */ + pending_plan_update?: { + plan?: string + /** Format: date-time */ + scheduled_for?: Date + } | null + /** Cambio programado de funcionalidades adicionales, si existe. */ + pending_add_ons_update?: { + add_ons?: string[] + /** Format: date-time */ + scheduled_for?: Date + } | null + domain?: string + custom_domain?: string + } + OrganizationDeleteCerts: { + /** + * Format: date-time + * Fecha de eliminación del certificado CSD. + */ + updated_at?: Date + } + OrganizationCreateInput: { + /** Nombre comercial de la organización. */ + name: string + } + OrganizationLegalInput: { + /** Nombre comercial de la organización. */ + name: string + /** Nombre Fiscal o Razón Social de la organización, *sin* el régimen societario (ej.: S.A. de C.V.). */ + legal_name: string + /** Código del Régimen Fiscal, del [catálogo del SAT](#régimen-fiscal). */ + tax_system: string + /** Sitio web de la organización, que aparecerá en el PDF y correos de facturas y recibos. */ + website?: string + /** Dirección de correo electrónico para aclaraciones. Aparecerá en el PDF y correos de facturas y recibos. */ + support_email?: string + /** Teléfono de la organización, que aparecerá en el PDF y correos de facturas y recibos. */ + phone?: string + address: Record & + components['schemas']['OrganizationAddress'] + } + OrganizationCertsInput: { + /** + * Format: binary + * Contenido binario del archivo con extensión `.cer` del certificado CSD. + */ + cer: BinaryDownload + /** + * Format: binary + * Contenido binario del archivo con extensión `.key` del certificado CSD. + */ + key: BinaryDownload + /** Contraseña de la llave del certificado. */ + password: string + } + OrganizationFielInput: { + /** + * Format: binary + * Contenido binario del archivo con extensión `.cer` de la e.firma (FIEL). + */ + cer: BinaryDownload + /** + * Format: binary + * Contenido binario del archivo con extensión `.key` de la e.firma (FIEL). + */ + key: BinaryDownload + /** Contraseña de la llave privada de la e.firma (FIEL). */ + password: string + } + OrganizationLogoInput: { + /** + * Format: binary + * Contenido binario del archivo con la imagen que se usará como + * logotipo. Formatos soportados: + * - jpg + * - png + * - svg + */ + file: BinaryDownload + } + OrganizationCustomizationInput: { + /** + * Format: hex + * Color distintivo de la marca en representación Hexadecimal RGB de 6 caracteres. + */ + color?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_number_test?: number + /** Configura qué campos opcionales se quieren mostrar en el PDF. El SAT no obliga a mostrar estos campos, pero pueden activarse según la preferencia de la organización. */ + pdf_extra?: { + /** + * Mostrar códigos de catálogos del SAT junto a sus descripciones. Ejemplo: “KGM Kilogramo”. + * @default true + */ + codes?: boolean + /** + * Mostrar la clave de producto-servicio. + * @default true + */ + product_key?: boolean + /** + * Mostrar los códigos estandarizados de estado y de país en el PDF. + * @default true + */ + address_codes?: boolean + /** + * Mostrar la clave de exportación en el PDF. + * @default false + */ + export_key?: boolean + /** + * Redondear el precio unitario en el PDF a 2 decimales, pero conservar los 6 decimales en el XML. + * @default false + */ + round_unit_price?: boolean + /** + * Mostrar el desglose de impuestos en el PDF. Si se desactiva, sólo se mostratán los impuestos en los totales, pero no en el detalle de cada concepto. + * @default true + */ + tax_breakdown?: boolean + /** + * Mostrar el desglose de IEPS en el PDF. Si se desactiva, solo se mostrarán los impuestos relacionados al IVA en el subtotal. + * @default true + */ + ieps_breakdown?: boolean + /** + * Suma IEPS con subtotal sin desglosarlo en el PDF. + * @default false + */ + combine_ieps_with_subtotal?: boolean + /** + * Renderizar el complemento de Carta Porte 3.1 en el PDF sólo si el complemento de carta porte está incluido en la factura. + * @default false + */ + render_carta_porte?: boolean + /** + * Renderizar el complemento de Instituciones Educativas Privadas en el PDF. + * @default false + */ + render_iedu?: boolean + /** + * Renderizar el complemento de hidrocarburos y petrolíferos en el PDF. + * @default false + */ + render_hyp_complement?: boolean + /** + * Renderizar el complemento de comercio exterior en el PDF. + * @default false + */ + render_comercio_exterior?: boolean + /** + * Repetir la firma electrónica en cada página del PDF. + * @default false + */ + repeat_signature?: boolean + payroll_options?: { + /** @default false */ + tipo_contrato?: boolean + /** @default false */ + puesto?: boolean + /** @default false */ + riesgo_puesto?: boolean + /** @default false */ + antiguedad?: boolean + } + } + } + OrganizationReceiptsInput: { + /** + * Periodicidad con la que la empresa decide realizar una factura global + * (al público en general) por todos los recibos no facturados. Este + * valor se utiliza como default al crear una factura global. + * @default month + * @enum {string} + */ + periodicity?: InvoicingPeriod + /** + * Días máximos para facturar por medio del portal de autofactura + * después de emitido el recibo y antes del último día del periodo + * definido por el atributo `periodicity`. El valor `0` desactiva esta + * opción, haciendo que los recibos expiren siempre el último día del + * periodo. + * @default 7 + */ + duration_days?: number + /** Número de folio que se asignará al siguiente recibo creado en esta organización en ambiente Live. */ + next_folio_number?: number + /** Número de folio que se asignará al siguiente recibo creado en esta organización en ambiente Test. */ + next_folio_number_test?: number + /** + * Activa o desactiva la generación automática de una factura global después + * de cerrar cada periodo configurado. Para activarla, la organización debe + * tener contratado el feature de factura global. + * @default false + */ + activate_global_invoice?: boolean + /** + * Cuando es `true`, agrupa conceptos equivalentes al facturar varios recibos + * seleccionados, incluyendo las autofacturas. No aplica a las facturas globales. + * @default false + */ + grouped_items_invoice?: boolean + } + OrganizationSelfInvoiceInput: { + /** Lista de usos CFDI permitidos para la autofactura. Si este campo está vacío, se permitirán todos los usos CFDI. */ + allowed_cfdi_uses?: string[] + /** + * Indica si la organización aplica el ISR bajo el régimen RESICO. Si es verdadero, el ISR se calculará de acuerdo con el régimen RESICO. + * Si es falso, el ISR se calculará de acuerdo con el régimen general. + */ + apply_resico_isr?: boolean + /** + * Dirección de correo electrónico para aclaraciones. Aparecerá en el portal de autofacturación. + * Al modificarlo se enviará un correo de verificación a la nueva dirección. + */ + support_email?: string + } + /** + * Nombre del dominio. Se permiten caracteres alfanuméricos, sólo minúsculas, + * guión (-) y guión bajo (_). Debe empezar con una letra y + * terminar en letra o número. + */ + DomainField: string + OrganizationDomainInput: { + domain: components['schemas']['DomainField'] + } + OrganizationSeriesCreateInput: { + /** Nombre de la serie. */ + series: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test: number + } + OrganizationSeriesUpdateInput: { + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test?: number + } + OrganizationSeriesDefaultInput: { + /** + * Tipo de comprobante. Valores posibles: + * `I` (Ingreso), `E` (Egreso), `P` (Pago), `N` (Nómina), `T` (Traslado). + * @enum {string} + */ + type: InvoiceType + /** Nombre de la serie. */ + series: string + } + /** Objeto Series */ + OrganizationSeriesGroup: { + /** Nombre de la serie. */ + series?: string + /** Número de folio que se asignará a la siguiente factura en ambiente Live (y que se incrementará automáticamente por cada nueva factura). */ + next_folio?: number + /** Número de folio que se asignará a la siguiente factura en ambiente Test (y que se incrementará automáticamente por cada nueva factura). */ + next_folio_test?: number + } + OkResponse: { + ok: boolean + } + OrganizationInvite: { + /** Identificador único de la invitación. */ + id?: string + /** + * Format: date-time + * Fecha y hora en que se creó la invitación. + */ + created_at: Date + /** + * Format: email + * Correo electrónico al que se envió la invitación. + */ + email?: string + /** Nombre de la organización que envió la invitación. */ + organization_name?: string + /** ID del rol asignado en la invitación, si existe. */ + role?: string | null + /** Nombre del rol asignado en la invitación, si existe. */ + role_name?: string | null + /** Lista de roles visibles que describe el acceso otorgado por la invitación. */ + roles?: string[] + /** + * Format: date-time + * Fecha y hora en que expira la invitación. + */ + expires_at: Date | null + } + /** Lista de invitaciones de organización. */ + OrganizationInviteList: components['schemas']['OrganizationInvite'][] + OrganizationPermissionRole: { + /** Identificador único del rol. */ + id?: string + /** Nombre del rol. */ + name?: string + /** Código de plantilla base del rol, si proviene de una plantilla del sistema. */ + template_code?: string | null + /** ID de la organización a la que pertenece el rol. */ + organization?: string | null + /** Número de usuarios que actualmente usan este rol. */ + used_by?: number + /** Operaciones agregadas al rol además de las definidas por su plantilla. */ + overrides_add?: string[] + /** Operaciones removidas del rol respecto a su plantilla. */ + overrides_remove?: string[] + /** Lista final de operaciones permitidas por este rol. */ + operations?: string[] + /** + * Format: date-time + * Fecha y hora de creación del rol. + */ + created_at: Date | null + /** + * Format: date-time + * Fecha y hora de la última actualización del rol. + */ + updated_at: Date | null + } + /** Lista de roles configurables de la organización. */ + OrganizationPermissionRoleList: components['schemas']['OrganizationPermissionRole'][] + OrganizationPermissionRoleTemplate: { + /** + * Código interno de la plantilla de rol. + * @enum {string} + */ + code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + /** Nombre visible de la plantilla de rol. */ + label?: string + /** Operaciones incluidas por defecto en la plantilla. */ + operations?: string[] + } + /** Lista de plantillas de roles disponibles para la organización. */ + OrganizationPermissionRoleTemplateList: components['schemas']['OrganizationPermissionRoleTemplate'][] + /** Lista de operaciones disponibles para permisos a nivel organización. */ + OrganizationPermissionOperationList: string[] + OrganizationUserAccess: { + /** Identificador del acceso del usuario dentro de la organización. Para el propietario, este valor es `owner` porque su acceso es implícito. */ + id?: string + /** Nombre completo del usuario. */ + full_name?: string + /** + * Format: email + * Correo electrónico del usuario. + */ + email?: string + /** ID del rol asignado al usuario, si existe. Para el propietario, este valor es `null` porque su acceso es implícito. */ + role?: string | null + /** Nombre del rol asignado o del acceso implícito del usuario. Para el propietario, este valor es `owner`. */ + role_name?: string | null + /** ID de la organización a la que pertenece el acceso. */ + organization?: string | null + /** Lista final de operaciones permitidas para el usuario. */ + operations?: string[] + /** + * Format: date-time + * Fecha y hora en que se creó el acceso. Para el propietario, corresponde a la creación de la organización. + */ + created_at: Date + /** + * Format: date-time + * Fecha y hora de la última actualización del acceso. Para el propietario, corresponde a la creación de la organización porque su acceso es implícito. + */ + updated_at: Date + } + /** Lista de accesos de usuarios a la organización, incluyendo accesos implícitos como el del propietario. */ + OrganizationUserAccessList: components['schemas']['OrganizationUserAccess'][] + OrganizationInviteCreateInput: { + /** + * Format: email + * Correo electrónico del usuario que será invitado. + */ + email: string + /** ID de rol personalizado de la organización. */ + role?: string + } + OrganizationInviteRespondInput: { + /** Indica si la invitación debe aceptarse (`true`) o rechazarse (`false`). */ + accept: boolean + } + OrganizationPermissionRoleCreateInput: { + /** Nombre del rol. */ + name: string + /** + * Código de plantilla base para inicializar el rol, si aplica. + * @enum {string|null} + */ + template_code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + | null + /** Operaciones adicionales que se agregarán al rol. */ + add?: string[] + /** Operaciones que se removerán del rol. */ + remove?: string[] + } + OrganizationPermissionRoleUpdateInput: { + /** Nuevo nombre del rol. */ + name?: string + /** + * Nuevo código de plantilla base del rol, si aplica. + * @enum {string|null} + */ + template_code?: + | 'org-admin' + | 'org-readonly' + | 'org-billing' + | 'org-developer' + | 'org-team-manager' + | null + /** Lista completa de operaciones extra que debe conservar el rol. */ + add?: string[] + /** Lista completa de operaciones removidas que debe conservar el rol. */ + remove?: string[] + } + OrganizationUserAccessRoleUpdateInput: { + /** ID del rol que se asignará al usuario. */ + role: string + } + } + responses: { + /** Error en parámetros de la petición */ + BadRequest: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Error de autenticación */ + Unauthenticated: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Conflicto en la petición. La operación que se intenta realizar no puede completarse debido a conflictos en el estado actual del recurso. */ + Conflict: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** No se encontró el recurso especificado. */ + NotFound: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Demasiadas solicitudes en una ventana de tiempo corta. */ + RateLimited: { + headers: { + /** Segundos recomendados antes de reintentar. */ + 'Retry-After'?: number + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Error inesperado */ + UnexpectedError: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** Se requiere una suscripción activa y acceso al ambiente Live. */ + InvoiceZipRequestAccessRequired: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** No existen facturas válidas que coincidan con los filtros. */ + InvoiceZipRequestNoInvoices: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** La solicitud no existe o no pertenece a la organización o ambiente actuales. */ + InvoiceZipRequestNotFound: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + /** La generación del ZIP todavía no ha terminado. */ + InvoiceZipRequestNotReady: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GenericError'] + } + } + } + parameters: { + /** Identificador de la solicitud de ZIP. */ + InvoiceZipRequestId: string + /** Objeto con rango de fechas solicitado. */ + SearchDate: components['schemas']['DateRange'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + SearchPage: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + SearchLimit: number + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + SearchPagination: 'page' | 'cursor' + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + SearchAfter: string + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + SearchBefore: string + } + requestBodies: { + CustomerCreate: { + content: { + 'application/json': components['schemas']['CustomerCreateInput'] + } + } + CustomerEdit: { + content: { + 'application/json': components['schemas']['CustomerProperties'] + } + } + ProductCreate: { + content: { + 'application/json': components['schemas']['ProductProperties'] + } + } + ProductEdit: { + content: { + 'application/json': components['schemas']['ProductEditableProperties'] + } + } + InvoiceCreate: { + content: { + 'application/json': components['schemas']['InvoiceCreateInput'] + } + } + InvoiceCreatePending: { + content: { + 'application/json': + | components['schemas']['InvoiceIngresoInput'] + | components['schemas']['InvoiceEgresoInput'] + | components['schemas']['InvoicePagoInput'] + | components['schemas']['InvoiceNominaInput'] + | components['schemas']['InvoiceTrasladoInput'] + } + } + InvoiceEdit: { + content: { + 'application/json': + | components['schemas']['InvoiceIngresoEditInput'] + | components['schemas']['InvoiceEgresoEditInput'] + | components['schemas']['InvoicePagoEditInput'] + | components['schemas']['InvoiceNominaEditInput'] + | components['schemas']['InvoiceTrasladoEditInput'] + } + } + ReceiptCreate: { + content: { + 'application/json': components['schemas']['ReceiptInput'] + } + } + ReceiptAssignCustomer: { + content: { + 'application/json': components['schemas']['ReceiptAssignCustomerInput'] + } + } + ReceiptInvoice: { + content: { + 'application/json': components['schemas']['InvoiceReceiptInput'] + } + } + ReceiptCreateGlobalInvoice: { + content: { + 'application/json': components['schemas']['GlobalInvoiceInput'] + } + } + ReceiptCreateToInvoice: { + content: { + 'application/json': components['schemas']['ToInvoiceInput'] + } + } + ReceiptPreviewToInvoice: { + content: { + 'application/json': components['schemas']['ToInvoicePreviewInput'] + } + } + RetentionCreate: { + content: { + 'application/json': components['schemas']['RetentionInput'] + } + } + RetentionUpdate: { + content: { + 'application/json': components['schemas']['RetentionUpdateInput'] + } + } + OrganizationCreate: { + content: { + 'application/json': components['schemas']['OrganizationCreateInput'] + } + } + OrganizationEditLegal: { + content: { + 'application/json': components['schemas']['OrganizationLegalInput'] + } + } + OrganizationUploadCerts: { + content: { + 'multipart/form-data': components['schemas']['OrganizationCertsInput'] + } + } + OrganizationUploadFiel: { + content: { + 'multipart/form-data': components['schemas']['OrganizationFielInput'] + } + } + OrganizationUploadLogo: { + content: { + 'multipart/form-data': components['schemas']['OrganizationLogoInput'] + } + } + OrganizationEditCustomization: { + content: { + 'application/json': components['schemas']['OrganizationCustomizationInput'] + } + } + OrganizationEditReceiptsSettings: { + content: { + 'application/json': components['schemas']['OrganizationReceiptsInput'] + } + } + OrganizationEditSelfInvoiceSettings: { + content: { + 'application/json': components['schemas']['OrganizationSelfInvoiceInput'] + } + } + OrganizationEditDomain: { + content: { + 'application/json': components['schemas']['OrganizationDomainInput'] + } + } + OrganizationSeriesCreate: { + content: { + 'application/json': components['schemas']['OrganizationSeriesCreateInput'] + } + } + OrganizationSeriesUpdate: { + content: { + 'application/json': components['schemas']['OrganizationSeriesUpdateInput'] + } + } + OrganizationSeriesDefault: { + content: { + 'application/json': components['schemas']['OrganizationSeriesDefaultInput'] + } + } + OrganizationInviteCreate: { + content: { + 'application/json': components['schemas']['OrganizationInviteCreateInput'] + } + } + OrganizationInviteRespond: { + content: { + 'application/json': components['schemas']['OrganizationInviteRespondInput'] + } + } + OrganizationPermissionRoleCreate: { + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleCreateInput'] + } + } + OrganizationPermissionRoleUpdate: { + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleUpdateInput'] + } + } + OrganizationUserAccessRoleUpdate: { + content: { + 'application/json': components['schemas']['OrganizationUserAccessRoleUpdateInput'] + } + } + WebhookCreate: { + content: { + 'application/json': components['schemas']['WebhookCreateInput'] + } + } + WebhookEdit: { + content: { + 'application/json': components['schemas']['WebhookCreateEdit'] + } + } + } + headers: never + pathItems: never +} +export type $defs = Record +export interface operations { + searchCartaPorteAirTransportCodes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `airline_name` o `icao_designator`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchComercioExteriorTariffFractions: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteTransportConfigs: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteRightsOfPassage: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `right_of_passage` o `concessionaire`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteCustomsDocuments: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPortePackagingTypes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteTrailerTypes: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteHazardousMaterials: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `description` o `class_division`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteNavalAuthorizations: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchResult'] & { + data?: { + key?: string + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPortePortStations: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key`, `description` o `iata_designator`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchCartaPorteMarineContainers: { + parameters: { + query: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Prefijo para buscar en `key` o `description`. */ + q: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Búsqueda exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SearchKeyDescriptionResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listCustomers: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en `legal_name` (nombre fiscal) o en `tax_id` (RFC). */ + q?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['CustomerSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createCustomer: { + parameters: { + query?: { + /** + * Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. + * Además, pasar el valor `true` desactivará la validación de información fiscal con el SAT, + * permitiendo crear clientes con información incompleta. + * Con `true`, el body sigue `CustomerCreateWithEditLinkInput`; en otro caso sigue `CustomerCreateInput`. + */ + createEditLink?: boolean + } + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['CustomerCreate'] + responses: { + /** Un objeto `Customer` con la misma información ya existía */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + /** Nuevo objeto `Customer` creado */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Customer` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editCustomer: { + parameters: { + query?: { + /** + * Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. Pasar el valor `true` al editar + * **no** desactivará la validación de información fiscal con el SAT. + */ + createEditLink?: boolean + } + header?: never + path: { + /** ID del objeto a editar */ + customer_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['CustomerEdit'] + responses: { + /** Objeto `Customer` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Customer` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Customer'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendEditLinkByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto `Customer` a editar */ + customer_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Correo electrónico del cliente. Si no se proporciona, se usará el correo electrónico del cliente. */ + email?: string + } + } + } + responses: { + /** Enlace de edición enviado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el enlace se envió correctamente */ + ok?: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + validateCustomerTaxInfo: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto `Customer` a validar */ + customer_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la validación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si la información fiscal del cliente coincide con los registros del SAT */ + is_valid: boolean + /** Detalles de validación fiscal. Es un array vacío cuando `is_valid` es `true`. */ + errors: { + /** + * Indica que Facturapi generó el detalle de validación. + * @enum {string} + */ + source: 'facturapi' + /** Código estable del detalle de validación. */ + code: string + /** Ruta del campo cuya información fiscal no es válida. */ + path?: string + /** Mensaje descriptivo del detalle de validación. */ + message: string + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listProducts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción del producto o SKU. */ + q?: string + /** SKU del producto. */ + sku?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ProductSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createProduct: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ProductCreate'] + responses: { + /** Nuevo objeto `Product` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + product_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Product` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + product_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ProductEdit'] + responses: { + /** Objeto `Product` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteProduct: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + product_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Product` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Product'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listInvoices: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** + * Consulta. Texto a buscar en la factura. + * + * La búsqueda se realizará por coincidencias **parciales** en los campos: + * + * - `items[].product.description` + * - `customer.legal_name` + * + * Y por coincidencias **exactas** en los campos: + * + * - `id` + * - `uuid` + * - `customer.tax_id` + * - `folio_number` + * - `total` + */ + q?: string + /** Identificador del cliente. Útil para obtener las facturas emitidas a un sólo cliente. */ + customer?: string + /** Tipo de factura. Búsqueda por tipo de factura con las claves exactas. */ + type?: 'I' | 'E' | 'P' | 'N' | 'T' + /** Método de pago. Búsqueda exacta por método de pago. */ + payment_method?: 'PUE' | 'PPD' + /** Filtrar por folio de la factura. Coincidencia exacta. */ + folio_number?: number + /** Filtrar por serie de la factura. Coincidencia exacta. */ + series?: string + /** Filtrar por identificador externo. Coincidencia exacta. */ + external_id?: string + /** Filtrar por tipo de emisión. */ + issuer_type?: components['schemas']['IssuingType'] + /** Filtrar por uno o más estados de cancelación. */ + cancellation_status?: components['schemas']['CancellationStatus'][] + /** Filtrar por el UUID del CFDI. Coincidencia exacta. */ + uuid?: string + /** Filtrar por estado de pago. Coincidencia exacta. */ + payment_status?: 'paid' | 'unpaid' + /** Objeto con rango de fechas solicitado. El rango filtra el campo `date` de la factura. */ + date?: components['schemas']['DateRange'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: number + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createInvoice: { + parameters: { + query?: { + /** + * Útil para facturas de gran tamaño. Si se envía `false` o no se envía, la llamada esperará a que el SAT responda timbrando la factura. + * Si se envía `true`, la llamada regresará inmediatamente con el objeto `invoice` en status `pending`, y podrá consultarse su cambio de status + * a `valid` en un momento posterior. + */ + async?: boolean + } + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceCreate'] + responses: { + /** Nuevo objeto `Invoice` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | components['schemas']['Invoice'] + | components['schemas']['InvoiceDraft'] + } + } + /** Solicitud aceptada; Facturapi intentará recuperar el CFDI hasta cinco veces, una cada 10 minutos */ + 202: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] & { + /** @enum {string} */ + status: 'pending' + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDraftInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + invoice_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** Objeto `Invoice` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceDraft'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelInvoice: { + parameters: { + query?: { + /** + * Requerido para documentos emitidos; omite los parámetros para eliminar un borrador. + * Clave que representa el motivo de la cancelación de la factura. + * + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra factura. + * - `03`: **No se llevó a cabo la operación**. Cuando la venta o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la factura global**. Cuando se requiere cancelar + * una factura al público en general porque el cliente solicita su comprobante. + */ + motive?: '01' | '02' | '03' | '04' + /** + * ID de la factura que sustituye a la factura que se está cancelando. + * + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + */ + substitution?: string + } + header?: never + path: { + /** ID de la factura a cancelar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Solicitud de cancelación exitosa */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + copyToDraftInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID de la factura a copiar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Nuevo objeto `Invoice` con status `draft`. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceDraft'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + stampDraftInvoice: { + parameters: { + query?: { + /** + * Útil para facturas de gran tamaño. Si se envía `false` o no se envía, la llamada esperará a que el SAT responda timbrando la factura. + * Si se envía `true`, la llamada regresará inmediatamente con el objeto `invoice` en status `pending`, y podrá consultarse su cambio de status + * a `valid` en un momento posterior. + */ + async?: boolean + } + header?: never + path: { + /** ID del objeto a timbrar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` timbrado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateInvoiceStatus: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto invoice a actualizar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Invoice` actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoicePaymentSummary: { + parameters: { + query: { + /** Monto que se paga de esta factura, expresado en la divisa de la factura. No puede exceder el saldo pendiente. */ + amount: number + } + header?: never + path: { + /** ID de la factura de ingreso (método de pago PPD) que se desea pagar */ + invoice_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Resumen del documento relacionado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** UUID de la factura */ + uuid: string + /** Folio de la factura. Se omite si la factura no lo tiene registrado. */ + folio_number?: number + /** Serie de la factura */ + series: string | null + /** Número de parcialidad que corresponde a este pago */ + installment: number + /** Saldo pendiente de la factura antes de aplicar este pago */ + last_balance: number + /** Total de la factura */ + total: number + /** Divisa de la factura */ + currency: string + /** Monto que se paga en esta parcialidad */ + amount: number + /** Impuestos de la factura prorrateados al monto pagado */ + taxes: { + /** Base del impuesto prorrateada al monto pagado */ + base: number + /** Tasa o cuota del impuesto */ + rate: number + /** + * Tipo de impuesto (IVA, ISR, etc.) + * @enum {string} + */ + type: TaxType + /** + * Tipo de factor (Tasa, Exento, etc.) + * @enum {string} + */ + factor: TaxFactor + /** Indica si se trata de una retención */ + withholding: boolean + }[] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + previewInvoicePdf: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** El archivo PDF de la factura */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/pdf': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + previewInvoicePdfUrl: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['InvoiceEdit'] + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadInvoice: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del comprobante CFDI en el formato solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoiceDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'pdf' | 'xml' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadCancellationReceiptXml: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del acuse de recibo de cancelación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getCancellationReceiptDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + invoice_id: string + /** Formato del acuse de cancelación */ + format: 'xml' | 'pdf' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendInvoiceByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + invoice_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar la factura. Si no se envía este parámetro, la factura será enviada al correo que el cliente tenga registrado. */ + email?: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listInvoiceZipRequests: { + parameters: { + query?: { + /** Año a filtrar. Debe enviarse junto con `month`. */ + year?: number + /** Mes a filtrar. Debe enviarse junto con `year`. */ + month?: number + /** Status de la solicitud. */ + status?: components['schemas']['InvoiceZipRequestStatus'] + /** Filtra facturas emitidas o recibidas. */ + issuer_type?: components['schemas']['IssuingType'] + /** Filtra por un tipo de factura o por un arreglo normalizado exacto. */ + invoice_types?: components['schemas']['InvoiceZipRequestInvoiceType'][] + /** Página de resultados, empezando en 1. */ + page?: number + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado paginado de solicitudes de ZIP. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequestSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceZipRequestCreateInput'] + } + } + responses: { + /** Solicitud de ZIP creada o recuperada correctamente. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequest'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNoInvoices'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + retrieveInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Solicitud de ZIP recuperada correctamente. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InvoiceZipRequest'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadInvoiceZipRequest: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo ZIP generado. */ + 200: { + headers: { + /** Nombre sugerido con formato `attachment; filename="YYYY-MM.zip"`. */ + 'Content-Disposition'?: string + [name: string]: unknown + } + content: { + 'application/zip': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 409: components['responses']['InvoiceZipRequestNotReady'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getInvoiceZipRequestDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** Identificador de la solicitud de ZIP. */ + id: components['parameters']['InvoiceZipRequestId'] + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 402: components['responses']['InvoiceZipRequestAccessRequired'] + 404: components['responses']['InvoiceZipRequestNotFound'] + 409: components['responses']['InvoiceZipRequestNotReady'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listReceipts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de los conceptos del recibo o el SKU. */ + q?: string + /** ID del cliente asociado al recibo. */ + customer?: string + /** Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). Si se incluye, los recibos se agruparán y se listarán de acuerdo a la forma de pago. */ + payment_form?: string + /** Fecha de creación mayor o igual a la especificada. */ + 'date[gte]'?: Date + /** Fecha de creación menor o igual a la especificada. */ + 'date[lte]'?: Date + /** ID de la factura relacionada al recibo. */ + invoice?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ReceiptSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createReceipt: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreate'] + responses: { + /** Nuevo objeto `Receipt` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Receipt` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + assignReceiptCustomer: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a actualizar */ + receipt_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ReceiptAssignCustomer'] + responses: { + /** Objeto `Receipt` actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a cancelar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto 'Receipt' cancelado exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Receipt'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + invoiceReceipt: { + parameters: { + query?: never + header?: never + path: { + /** ID del recibo a facturar */ + receipt_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['ReceiptInvoice'] + responses: { + /** Nuevo objeto `Invoice` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createToInvoiceFromReceipts: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreateToInvoice'] + responses: { + /** Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | components['schemas']['Invoice'] + | components['schemas']['ToInvoiceSummary'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 500: components['responses']['UnexpectedError'] + } + } + previewToInvoiceFromReceipts: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptPreviewToInvoice'] + responses: { + /** Contenido binario del PDF */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/pdf': BinaryDownload + } + } + /** No se encontraron recibos elegibles para las keys enviadas */ + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 500: components['responses']['UnexpectedError'] + } + } + previewToInvoiceFromReceiptsUrl: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptPreviewToInvoice'] + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createGlobalInvoice: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['ReceiptCreateGlobalInvoice'] + responses: { + /** Nuevo objeto `Invoice` creado, o `null` si no hay recibos abiertos en el periodo */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Invoice'] | null + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadReceiptPdf: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del recibo digital en formato PDF */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getReceiptDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + receipt_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendReceiptByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + receipt_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar el recibo digital. */ + email: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listRetentions: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en el nombre fiscal del cliente o su RFC. */ + q?: string + /** Identificador del cliente. Útil para obtener las retenciones emitidas a un sólo cliente. */ + customer?: string + /** Filtrar por uno o más estados de retención. Si se omite, no se filtra por estado, equivalente a `all`. Enviar `all` también desactiva este filtro. */ + status?: ( + 'all' | 'draft' | 'pending' | 'valid' | 'canceled' | 'failed' + )[] + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['RetentionSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createRetention: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['RetentionCreate'] + responses: { + /** Nuevo objeto `Retention` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a editar */ + retention_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['RetentionUpdate'] + responses: { + /** Objeto `Retention` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + cancelRetention: { + parameters: { + query?: { + /** + * Clave que representa el motivo de la cancelación de la retención. + * Requerido para retenciones que no son borrador. + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra retención. + * - `03`: **No se llevó a cabo la operación**. Cuando la operación o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la retención global**. Cuando se requiere cancelar + * una retención al público en general porque el cliente solicita su comprobante. + */ + motive?: '01' | '02' | '03' | '04' + /** + * ID de la retención que sustituye a la retención que se está cancelando + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + */ + substitution?: string + } + header?: never + path: { + /** ID de la retención a cancelar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` cancelado exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + copyToDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a copiar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Nuevo objeto `Retention` con status `draft`. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + stampDraftRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID de la retención a timbrar */ + retention_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Retention` timbrado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Retention'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + downloadRetention: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + retention_id: string + /** Formato del archivo de descarga */ + format: 'xml' | 'pdf' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Archivo del comprobante CFDI en el formato solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/octet-stream': BinaryDownload + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getRetentionDownloadUrl: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a descargar */ + retention_id: string + /** Formato del archivo de descarga */ + format: 'pdf' | 'xml' | 'zip' + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['SignedDownloadUrl'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + sendRetentionByEmail: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + retention_id: string + } + cookie?: never + } + requestBody?: { + content: { + 'application/json': { + /** Dirección de correo electrónico a enviar la retención. Si no se envía este parámetro, la retención será enviada al correo que el cliente tenga registrado. */ + email?: string | string[] + } + } + } + responses: { + /** Objeto genérico de respuesta */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el correo fue enviado exitosamente */ + ok: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizations: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en `name` (nombre comercial), `legal_name` (nombre fiscal) o en `tax_id` (RFC). */ + q?: string + /** Objeto con rango de fechas solicitado. */ + date?: components['parameters']['SearchDate'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganization: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['OrganizationCreate'] + responses: { + /** Nuevo objeto `Organization` creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + meOrganization: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganization: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganization: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationLegal: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditLegal'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationCertificate: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadCerts'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationCertificate: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationDeleteCerts'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationFiel: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización. También puedes usar `me` con la Live Secret Key de la organización. */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadFiel'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + uploadOrganizationLogo: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUploadLogo'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationCustomization: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditCustomization'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationReceiptsSettings: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditReceiptsSettings'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationSelfInvoiceSettings: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditSelfInvoiceSettings'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + checkDomainAvailability: { + parameters: { + query: { + domain: components['schemas']['DomainField'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Información de disponibilidad de dominio */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Indica si el dominio está diponible */ + available: boolean + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editOrganizationDomain: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationEditDomain'] + responses: { + /** Objeto `Organization` modificado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Organization'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getTestApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Test API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + renewTestApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Test API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listLiveApiKeys: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Primeros 12 caracteres de la llave secreta */ + first_12: string + /** + * Format: date-time + * Fecha de creación de la llave secreta + */ + created_at: Date + /** ID de la llave secreta */ + id: string + }[] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + renewLiveApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': string + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteLiveApiKey: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID de la llave secreta a eliminar */ + id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Live API Key */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + /** Primeros 12 caracteres de la llave secreta */ + first_12?: string + /** + * Format: date-time + * Fecha de creación de la llave secreta + */ + created_at?: Date + /** ID de la llave secreta */ + id?: string + }[] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Listado de objetos `Series` creadas previamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data?: components['schemas']['OrganizationSeriesGroup'][] + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesCreate'] + responses: { + /** Nuevo objeto de la `Serie` creada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateDefaultSeries: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesDefault'] + responses: { + /** Serie predeterminada actualizada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 500: components['responses']['UnexpectedError'] + } + } + updateSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Nombre de la serie */ + series_name: string + } + cookie?: never + } + requestBody?: components['requestBodies']['OrganizationSeriesUpdate'] + responses: { + /** Objeto `Serie` editada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteSeriesGroup: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Nombre de la serie */ + series_name: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Serie` eliminado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationSeriesGroup'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationTeam: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de accesos de usuarios dentro de la organización, incluyendo accesos implícitos como el del propietario */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccessList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationTeamInvites: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de invitaciones enviadas y aún vigentes para la organización */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInviteList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganizationTeamInvite: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationInviteCreate'] + responses: { + /** Invitación creada o actualizada para el correo solicitado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInvite'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationTeamUser: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Detalle del acceso del usuario dentro de la organización, incluyendo accesos implícitos como el del propietario */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccess'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + removeOrganizationUserAccess: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Usuario removido de la organización */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationTeamInvite: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** Clave pública de la invitación. */ + invite_key: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Invitación cancelada */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listPendingOrganizationInvites: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Lista de invitaciones recibidas por el usuario autenticado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationInviteList'] + } + } + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + respondOrganizationInvite: { + parameters: { + query?: never + header?: never + path: { + /** Clave pública de la invitación. */ + invite_key: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationInviteRespond'] + responses: { + /** Invitación aceptada o rechazada exitosamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionRoles: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de roles */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationPermissionRoleCreate'] + responses: { + /** Rol creado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionRoleTemplates: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Plantillas disponibles */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRoleTemplateList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listOrganizationPermissionOperations: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Lista de códigos de operación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionOperationList'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Detalle del rol */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationPermissionRoleUpdate'] + responses: { + /** Rol actualizado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationPermissionRole'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteOrganizationPermissionRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del rol */ + role_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Rol eliminado */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OkResponse'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 409: components['responses']['Conflict'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + updateOrganizationTeamUserRole: { + parameters: { + query?: never + header?: never + path: { + /** ID de la organización */ + organization_id: string + /** ID del acceso */ + access_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['OrganizationUserAccessRoleUpdate'] + responses: { + /** Acceso del usuario actualizado con el nuevo rol */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationUserAccess'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + listWebhooks: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WebhookSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + createWebhook: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: components['requestBodies']['WebhookCreate'] + responses: { + /** Nuevo objeto `Webhook` creado */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + getWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a obtener */ + webhook_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Webhook` */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + editWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a editar */ + webhook_id: string + } + cookie?: never + } + requestBody: components['requestBodies']['WebhookEdit'] + responses: { + /** Objeto `Webhook` editado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + deleteWebhook: { + parameters: { + query?: never + header?: never + path: { + /** ID del objeto a eliminar */ + webhook_id: string + } + cookie?: never + } + requestBody?: never + responses: { + /** Objeto `Webhook` eliminado correctamente */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['Webhook'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + validateWebhookSignature: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': { + /** Llave secreta del webhook. Se obtiene al crear un webhook o desde el dashboard de Facturapi. */ + secret: string + /** Payload firmado. Prefiere el texto JSON original, conservando exactamente los bytes recibidos. También se aceptan objetos, pero la verificación utiliza su serialización JSON. */ + payload: + | string + | { + [key: string]: unknown + } + /** Firma del webhook recibida en el header `Facturapi-Signature` */ + signature: string + } + } + } + responses: { + /** Payload original con firma válida */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': + | string + | { + [key: string]: unknown + } + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + checkApiHealth: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** La API está operando con normalidad. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + ok?: boolean + } + } + } + /** Error de autenticación. Asegúrate de estar usando tu llave secreta. */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** Servicio temporalmente no disponible. */ + 502: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + validateTaxId: { + parameters: { + query: { + tax_id: string + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la validación */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['TaxIdValidationResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchProducts: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de la clasificación. */ + q?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ProductCatalogSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + searchUnits: { + parameters: { + query?: { + /** Modo de paginación de la búsqueda. `page` (por defecto) o `cursor` (recomendado para listas grandes). */ + pagination?: components['parameters']['SearchPagination'] + /** Devuelve los resultados posteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `before`. */ + after?: components['parameters']['SearchAfter'] + /** Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. */ + before?: components['parameters']['SearchBefore'] + /** Consulta. Texto a buscar en la descripción de la unidad de medida. */ + q?: string + /** Página de resultados a regresar, empezando desde la página 1. El máximo no es fijo; junto con `limit` debe caber dentro del tope de 3,000 resultados (con el `limit` por defecto de 100, la página máxima es 30). */ + page?: components['parameters']['SearchPage'] + /** Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. */ + limit?: components['parameters']['SearchLimit'] + } + header?: never + path?: never + cookie?: never + } + requestBody?: never + responses: { + /** Resultado de la búsqueda */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['UnitCatalogSearchResult'] + } + } + 400: components['responses']['BadRequest'] + 401: components['responses']['Unauthenticated'] + 404: components['responses']['NotFound'] + 429: components['responses']['RateLimited'] + 500: components['responses']['UnexpectedError'] + } + } + onInvoiceGlobalInvoiceCreated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceGlobalInvoiceCreatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceCreatedFromDashboard: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceCreatedFromDashboardEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onInvoiceCancellationStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InvoiceCancellationStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onReceiptSelfInvoiceComplete: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['ReceiptSelfInvoiceCompleteEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onReceiptStatusUpdated: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['ReceiptStatusUpdatedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + onCustomerEditLinkCompleted: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['CustomerEditLinkCompletedEvent'] + } + } + responses: { + /** OK */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } +} +type WithRequired = T & { + [P in K]-?: T[P] +} diff --git a/src/resources/customers.ts b/src/resources/customers.ts index c714584..0bcb8e2 100644 --- a/src/resources/customers.ts +++ b/src/resources/customers.ts @@ -1,97 +1,385 @@ -import { - Customer, - GenericResponse, - SearchResult, - TaxInfoValidation, -} from '../types'; -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { components as InputComponents } from '../generated/input' export default class Customers { - client: WrapperClient; - constructor(client: WrapperClient) { - this.client = client; - } + constructor(public client: WrapperClient) {} + /** + * Crear cliente + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @param params.createEditLink - Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. + * Además, pasar el valor `true` desactivará la validación de información fiscal con el SAT, + * permitiendo crear clientes con información incompleta. + * Con `true`, el body sigue `CustomerCreateWithEditLinkInput`; en otro caso sigue `CustomerCreateInput`. + * + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado + */ + create( + data: InputComponents['schemas']['CustomerCreateWithEditLinkInput'], + params: OperationQuery<'createCustomer'> & { createEditLink: true }, + ): Promise> + + /** + * Crear cliente + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @param params.createEditLink - Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. + * Además, pasar el valor `true` desactivará la validación de información fiscal con el SAT, + * permitiendo crear clientes con información incompleta. + * Con `true`, el body sigue `CustomerCreateWithEditLinkInput`; en otro caso sigue `CustomerCreateInput`. + * + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado + */ + create( + data: OperationBody<'createCustomer'>, + params?: OperationQuery<'createCustomer'> | null, + ): Promise> /** - * Creates a new customer in your organization - * @param data Customer data - * @param params Query params - * @returns Customer object + * Crear cliente + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @param params.createEditLink - Si pasas el valor `true`, se generará un enlace para que el cliente pueda editar + * su información fiscal. Este enlace estará disponible en el campo "edit_link", será + * válido por 3 días y sólo se podrá usar una vez. + * Además, pasar el valor `true` desactivará la validación de información fiscal con el SAT, + * permitiendo crear clientes con información incompleta. + * Con `true`, el body sigue `CustomerCreateWithEditLinkInput`; en otro caso sigue `CustomerCreateInput`. + * + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado */ create( - data: Record, - params: Record | null = null, - ): Promise { - return this.client.post('/customers', { body: data, params }); + data: + | OperationBody<'createCustomer'> + | InputComponents['schemas']['CustomerCreateWithEditLinkInput'], + params?: OperationQuery<'createCustomer'> | null, + ): Promise> { + return this.client.request>( + `/customers`, + { + method: 'POST', + datePlan: operationDatePlans.createCustomer, + body: data, + params: params, + }, + ) } /** - * Gets a paginated list of customers that belong to your organization - * @param params Search parameters - * @returns List of customers + * Crear cliente + * + * País MEX, u omitido. Requiere razón social, RFC, régimen fiscal y código postal. Los RFC genéricos usan CustomerGenericCreateInput. + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * Este método conserva los campos requeridos de su variante. Para crear un cliente con datos incompletos, usa create(data, { createEditLink: true }). + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado */ - list(params?: Record | null): Promise> { - if (!params) params = {}; - return this.client.get('/customers', { params: params }); + createNational( + data: InputComponents['schemas']['CustomerNationalCreateInput'], + params?: OperationQuery<'createCustomer'> | null, + ): Promise> { + return this.client.request>( + `/customers`, + { + method: 'POST', + datePlan: operationDatePlans.createCustomer, + body: data, + params: params, + }, + ) } /** - * Gets a single customer object - * @param id Customer Id - * @returns Customer object + * Crear cliente + * + * Requiere razón social y domicilio con un país explícito distinto de MEX. El identificador fiscal y el código postal son opcionales; el régimen fiscal predeterminado es 616. + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * Este método conserva los campos requeridos de su variante. Para crear un cliente con datos incompletos, usa create(data, { createEditLink: true }). + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado */ - retrieve(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/customers/' + id); + createForeign( + data: InputComponents['schemas']['CustomerForeignCreateInput'], + params?: OperationQuery<'createCustomer'> | null, + ): Promise> { + return this.client.request>( + `/customers`, + { + method: 'POST', + datePlan: operationDatePlans.createCustomer, + body: data, + params: params, + }, + ) } /** - * Updates a customer - * @param id Customer Id - * @param data Customer data to update - * @param params Query params - * @returns Updated customer + * Crear cliente + * + * RFC de público en general XAXX010101000 o RFC genérico extranjero XEXX010101000. Requiere razón social y RFC. El régimen fiscal predeterminado es 616. Si se envía domicilio mexicano, requiere código postal. + * + * Registra un nuevo cliente en Facturapi. + * + * Esta llamada valida que los datos fiscales coincidan con + * los registros del SAT para ese RFC, de lo contrario, la llamada + * devolverá un error indicando el problema. + * + * Una vez creado el cliente y obtenido un objeto de respuesta, + * te recomendamos guardar el ID en tu base de datos junto a la información + * de tu cliente. Posteriormente, puedes llamar al endpoint de Crear Factura + * pasando el ID del cliente en lugar de repetir la información. + * + * Por último, ten en cuenta que los clientes que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * Este método conserva los campos requeridos de su variante. Para crear un cliente con datos incompletos, usa create(data, { createEditLink: true }). + * + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @returns 200: Un objeto `Customer` con la misma información ya existía + * 201: Nuevo objeto `Customer` creado + */ + createGeneric( + data: InputComponents['schemas']['CustomerGenericCreateInput'], + params?: OperationQuery<'createCustomer'> | null, + ): Promise> { + return this.client.request>( + `/customers`, + { + method: 'POST', + datePlan: operationDatePlans.createCustomer, + body: data, + params: params, + }, + ) + } + + /** + * Listar clientes + * + * Regresa una lista paginada de todos los clientes de una organización o realiza una búsqueda de acuerdo a parámetros + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda + */ + list( + params?: OperationQuery<'listCustomers'> | null, + ): Promise> { + return this.client.request>( + `/customers`, + { + method: 'GET', + datePlan: operationDatePlans.listCustomers, + params: params, + }, + ) + } + + /** + * Obtener cliente por ID + * + * Regresa el objeto 'Customer' relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Customer` + */ + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/customers/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getCustomer }, + ) + } + + /** + * Editar cliente + * + * Actualiza la información de un cliente existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + * + * @param id - ID del objeto a editar + * @param data - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @returns Objeto `Customer` editado correctamente */ update( id: string, - data: Record, - params: Record | null = null, - ): Promise { - return this.client.put('/customers/' + id, { body: data, params }); + data: OperationBody<'editCustomer'>, + params?: OperationQuery<'editCustomer'> | null, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/customers/${encodeURIComponent(id)}`, + { + method: 'PUT', + datePlan: operationDatePlans.editCustomer, + body: data, + params: params, + }, + ) } /** - * Permanently removes a customer from your organization. - * @param id Customer Id - * @returns Deleted customer + * Eliminar cliente + * + * Elimina el cliente de tu organización. Las facturas asociadas al cliente **no** se eliminarán. + * + * @param id - ID del objeto a eliminar + * @returns Objeto `Customer` eliminado correctamente */ - del(id: string): Promise { - return this.client.delete('/customers/' + id); + del(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/customers/${encodeURIComponent(id)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteCustomer }, + ) } /** - * Validate customer with SAT validation. - * @param id Customer Id - * @returns Validation result + * Validar información fiscal + * + * Valida que la información fiscal del cliente coincida con los registros del SAT. + * + * Su función principal es validar que los datos del cliente registrado siguen cumpliendo la validación del SAT. + * + * :::tip + * Las operaciones de crear cliente, editar cliente y crear factura ya realizan una + * validación de la información del cliente, por lo que **no** es necesario llamar a este endpoint + * antes de realizar dichas operaciones. + * ::: + * + * @param id - ID del objeto `Customer` a validar + * @returns Resultado de la validación */ - validateTaxInfo(id: string): Promise { - return this.client.get('/customers/' + id + '/tax-info-validation'); + validateTaxInfo( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/customers/${encodeURIComponent(id)}/tax-info-validation`, + { method: 'GET', datePlan: operationDatePlans.validateCustomerTaxInfo }, + ) } /** - * Send the customer an email with a link to edit their information. - * @param id Customer Id - * @param options Email options - * @param options.email Email address to send the link to + * Enviar enlace de edición por correo electrónico + * + * Envía un enlace para que el cliente pueda editar su información fiscal. + * + * Este enlace estará disponible en el campo `edit_link`, será válido por 3 días y sólo se podrá usar una vez. + * + * @param id - ID del objeto `Customer` a editar + * @param options - Datos de la solicitud. + * @returns Enlace de edición enviado correctamente */ sendEditLinkByEmail( id: string, - options: { - email: string; - }, - ): Promise { - return this.client.post('/customers/' + id + '/email-edit-link', { - body: options, - }); + options: OperationBody<'sendEditLinkByEmail'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/customers/${encodeURIComponent(id)}/email-edit-link`, + { + method: 'POST', + datePlan: operationDatePlans.sendEditLinkByEmail, + body: options, + }, + ) } } diff --git a/src/resources/invoices.ts b/src/resources/invoices.ts index eb1f357..250bfb2 100644 --- a/src/resources/invoices.ts +++ b/src/resources/invoices.ts @@ -1,288 +1,659 @@ -import { - BinaryDownload, - CancelInvoiceOptions, - CreateZipRequestData, - GenericResponse, - Invoice, - ListZipRequestsParams, - PaymentSummary, - PaymentSummaryParams, - SearchResult, - SendEmailBody, - SignedDownloadUrl, - ZipRequest, -} from '../types'; -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { components as InputComponents } from '../generated/input' export default class Invoices { - client: WrapperClient; - - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Creates a new valid invoice (CFDI). - * @param body Invoice data - * @param params Query params - * @returns Invoice object + * Crear factura (CFDI 4.0) + * + * Crea una nueva Factura. Si la factura es creada en ambiente Live, ésta será **timbrada y enviada al SAT**. + * + * Revisa e infórmate sobre el [rescate de CFDI en intermitencias (Status 202)](https://docs.facturapi.io/docs/guides/invoices/intermitencias). + * + * @param body - Datos de la solicitud. + * @param params - Parámetros de consulta. + * @returns 200: Nuevo objeto `Invoice` creado + * 202: Solicitud aceptada; Facturapi intentará recuperar el CFDI hasta cinco veces, una cada 10 minutos */ create( - body: Record, - params?: Record | null, - ): Promise { - return this.client.post('/invoices', { body, params }); + body: OperationBody<'createInvoice'>, + params?: OperationQuery<'createInvoice'> | null, + ): Promise> { + return this.client.request>( + `/invoices`, + { + method: 'POST', + datePlan: operationDatePlans.createInvoice, + body: body, + params: params, + }, + ) } /** - * Gets a paginated list of invoices created by your organization - * @param params - Search parameters - * @returns Search results object. The object contains a `data` property with the list of invoices. + * Listar facturas + * + * Regresa una lista paginada de todas las facturas de una organización o realiza una búsqueda de acuerdo a parámetros. + * + * Por defecto, los resultados se ordenan por fecha de emisión, usando el campo `date` de forma descendente. + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - list(params?: Record | null): Promise> { - if (!params) params = {}; - return this.client.get('/invoices', { params }); + list( + params?: OperationQuery<'listInvoices'> | null, + ): Promise> { + return this.client.request>(`/invoices`, { + method: 'GET', + datePlan: operationDatePlans.listInvoices, + params: params, + }) } /** - * Gets a single invoice object - * @param id Invoice Id - * @returns Invoice object + * Obtener factura por ID + * + * Regresa el objeto 'Invoice' relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Invoice` */ - retrieve(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/' + id); + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getInvoice }, + ) } /** - * Gets the information needed to add this invoice as a related document in a - * payment complement (complemento de pago): the installment number according - * to the payment history, the previous balance, and the invoice tax breakdown - * prorated to the amount being paid. - * @param id Invoice Id - * @param params.amount Amount being paid, expressed in the invoice currency. Cannot exceed the outstanding balance. - * @returns Payment summary ready to be used as a related document + * Resumen de pago + * + * Devuelve la información necesaria para agregar esta factura como documento relacionado en un + * Comprobante de Pago (complemento de pago): el número de parcialidad que corresponde según el + * historial de pagos, el saldo anterior (`last_balance`) y el desglose de impuestos de la factura + * prorrateado al monto que se pretende pagar. + * + * El valor de retorno está listo para usarse como elemento de `related_documents` al + * [crear una factura de tipo Pago](https://docs.facturapi.io/api/#tag/invoice/operation/createInvoice). + * + * El parámetro `amount` debe expresarse en la divisa de la factura y no puede exceder el saldo + * pendiente (`amount_due`). Cuando el pago se recibe en otra divisa, convierte el monto antes de + * llamar este método. + * + * @param id - ID de la factura de ingreso (método de pago PPD) que se desea pagar + * @param params - Parámetros de consulta. + * @param params.amount - Monto que se paga de esta factura, expresado en la divisa de la factura. No puede exceder el saldo pendiente. + * @returns Resumen del documento relacionado */ paymentSummary( id: string, - params: PaymentSummaryParams, - ): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/' + id + '/payment-summary', { params }); + params: OperationQuery<'getInvoicePaymentSummary'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/payment-summary`, + { + method: 'GET', + datePlan: operationDatePlans.getInvoicePaymentSummary, + params: params, + }, + ) } /** - * Cancels an invoice. The invoice will not be valid anymore and will change its status to canceled. - * @param id Invoice Id - * @param params Cancel options - * @returns Canceled invoice + * Cancelar factura + * + * Realiza una solicitud de cancelación de factura ante el SAT, soportando el esquema de cancelación 2022. + * + * Al usar este método pueden ocurrir 3 posibles resultados: + * + * - Que la llamada regrese un error con la explicación de por qué no se pudo cancelar. + * - Que la llamada sea satisfactoria y regrese un objeto `invoice` con la propiedad `status: "canceled"`. + * - Que la llamada sea satisfactoria, pero que la cancelación requiera de confirmación de parte de tu cliente, en cuyo caso se obtendrá como respuesta el objeto `invoice` con las propiedades `status: "valid"` y `cancellation_status: "pending"`. + * + * En el tercer escenario, el valor de `cancellation_status` será actualizado automáticamente por Facturapi cuando tu cliente acepte, rechace o deje expirar la solicitud, de tal manera que al consultar una factura (usando [Obtener Factura](https://docs.facturapi.io/api/#tag/invoice/operation/getInvoice)), la propiedad `cancellation_status` reflejará el estado más reciente de la solicitud. + * + * Consulta los valores posibles de `cancellation_status` más abajo. + * + * Después de la cancelación la factura ya no tendrá validez, el objeto cambiará su `status` a `"canceled"` y seguirá estando disponible para futuras consultas. + * + * Si el status de la factura es `draft`, este método la eliminará de la base de datos. + * + * Si el status de la factura es `canceled`, este método regresará un error. + * + * @param id - ID de la factura a cancelar + * @param params - Parámetros de consulta. + * @param params.motive - Requerido para documentos emitidos; omite los parámetros para eliminar un borrador. + * Clave que representa el motivo de la cancelación de la factura. + * + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * factura contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra factura. + * - `03`: **No se llevó a cabo la operación**. Cuando la venta o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la factura global**. Cuando se requiere cancelar + * una factura al público en general porque el cliente solicita su comprobante. + * + * @param params.substitution - ID de la factura que sustituye a la factura que se está cancelando. + * + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + * + * @returns Solicitud de cancelación exitosa */ - cancel(id: string, params: CancelInvoiceOptions): Promise { - return this.client.delete('/invoices/' + id, { params }); + cancel( + id: string, + params?: InputComponents['schemas']['CancellationQueryInput'] | null, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}`, + { + method: 'DELETE', + datePlan: operationDatePlans.cancelInvoice, + params: params, + }, + ) } /** - * Sends the invoice to the customer's email - * @param id Invoice Id - * @param options Additional arguments - * @param options.email Email address to send the invoice to - * @returns Object with 'ok' property set to true if the email was sent successfully + * Enviar factura por correo electrónico + * + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + * + * @param id - ID del objeto a obtener + * @param options - Datos de la solicitud. + * @returns Objeto genérico de respuesta */ - sendByEmail(id: string, options?: SendEmailBody): Promise { - return this.client.post('/invoices/' + id + '/email', { body: options }); + sendByEmail( + id: string, + options?: OperationBody<'sendInvoiceByEmail'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/email`, + { + method: 'POST', + datePlan: operationDatePlans.sendInvoiceByEmail, + body: options, + }, + ) } /** - * Downloads the specified invoice in PDF format - * @param id Invoice Id - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Descargar factura + * + * Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - async downloadPdf(id: string): Promise { - return this.client.get('/invoices/' + id + '/pdf'); + downloadPdf(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/pdf`, + { method: 'GET', datePlan: operationDatePlans.downloadInvoice }, + ) } /** - * Downloads the specified invoice in XML format - * @param id Invoice Id - * @returns XML file in a stream (Node.js) or Blob (browser) + * Descargar factura + * + * Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - async downloadXml(id: string): Promise { - return this.client.get('/invoices/' + id + '/xml'); + downloadXml(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/xml`, + { method: 'GET', datePlan: operationDatePlans.downloadInvoice }, + ) } /** - * Downloads the specified invoice in a ZIP package containing both PDF and XML files - * @param id Invoice Id - * @returns ZIP file in a stream (Node.js) or Blob (browser) + * Descargar factura + * + * Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - downloadZip(id: string): Promise { - return this.client.get('/invoices/' + id + '/zip'); + downloadZip(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/zip`, + { method: 'GET', datePlan: operationDatePlans.downloadInvoice }, + ) } /** - * Gets a short-lived URL for downloading an invoice PDF directly. - * @param id Invoice Id - * @returns Signed download URL and its metadata + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la factura en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. */ - downloadPdfUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/' + id + '/download-url/pdf'); + downloadPdfUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/download-url/pdf`, + { method: 'GET', datePlan: operationDatePlans.getInvoiceDownloadUrl }, + ) } - /** Gets a short-lived URL for downloading an invoice XML file. */ - downloadXmlUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/' + id + '/download-url/xml'); + /** + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la factura en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadXmlUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/download-url/xml`, + { method: 'GET', datePlan: operationDatePlans.getInvoiceDownloadUrl }, + ) } - /** Gets a short-lived URL for downloading an invoice ZIP file. */ - downloadZipUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/' + id + '/download-url/zip'); + /** + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la factura en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadZipUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/download-url/zip`, + { method: 'GET', datePlan: operationDatePlans.getInvoiceDownloadUrl }, + ) } /** - * Creates or retrieves a ZIP request for invoices matching the specified criteria. - * @param data ZIP request criteria - * @returns ZIP request object + * Crear o recuperar solicitud de ZIP mensual + * + * Crea una solicitud para generar un archivo ZIP con las facturas de un mes, o recupera la solicitud existente con los mismos filtros. + * + * La operación es idempotente. Los tipos de factura se normalizan, por lo que `["I", "E"]` y `["E", "I"]` corresponden a la misma solicitud. Las llamadas concurrentes idénticas también regresan la misma solicitud. + * + * Si una solicitud anterior tiene status `failed`, volver a llamar este método reintentará su procesamiento. Antes del nuevo intento se limpian el error, la tarea anterior, el progreso procesado y la lista de documentos fallidos. Si no es posible programar la generación, la solicitud se guarda con status `failed` y la API regresa un error `5xx`. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. Las llaves de ambiente Test regresan HTTP 402. + * + * @param data - Datos de la solicitud. + * @returns Solicitud de ZIP creada o recuperada correctamente. */ - createZipRequest(data: CreateZipRequestData): Promise { - return this.client.post('/invoices/zip-requests', { body: data }); + createZipRequest( + data: OperationBody<'createInvoiceZipRequest'>, + ): Promise> { + return this.client.request>( + `/invoices/zip-requests`, + { + method: 'POST', + datePlan: operationDatePlans.createInvoiceZipRequest, + body: data, + }, + ) } /** - * Gets a paginated list of invoice ZIP requests. - * @param params Search parameters - * @returns Search results containing ZIP requests + * Listar solicitudes de ZIP mensual + * + * Regresa una lista paginada de solicitudes de ZIP. `year` y `month` deben enviarse juntos. `invoice_types` filtra por un tipo o por un arreglo normalizado exacto. + * + * Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + * + * @param params - Parámetros de consulta. + * @returns Resultado paginado de solicitudes de ZIP. */ listZipRequests( - params?: ListZipRequestsParams | null, - ): Promise> { - return this.client.get('/invoices/zip-requests', { - params: params || {}, - }); + params?: OperationQuery<'listInvoiceZipRequests'> | null, + ): Promise> { + return this.client.request>( + `/invoices/zip-requests`, + { + method: 'GET', + datePlan: operationDatePlans.listInvoiceZipRequests, + params: params, + }, + ) } /** - * Gets a single invoice ZIP request. - * @param id ZIP request Id - * @returns ZIP request object + * Recuperar solicitud de ZIP mensual + * + * Recupera una solicitud de ZIP. Consulta este método hasta que el status sea `finished` o `failed`. Cuando sea `finished`, descarga el archivo con el método de descarga. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + * + * @param id - Identificador de la solicitud de ZIP. + * @returns Solicitud de ZIP recuperada correctamente. */ - retrieveZipRequest(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/zip-requests/' + id); + retrieveZipRequest( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/zip-requests/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.retrieveInvoiceZipRequest }, + ) } /** - * Downloads the ZIP file generated by an invoice ZIP request. - * @param id ZIP request Id - * @returns ZIP file in a stream (Node.js) or Blob (browser) + * Descargar ZIP mensual + * + * Descarga el ZIP de una solicitud terminada. El nombre del archivo usa el formato `YYYY-MM.zip`. + * + * Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + * + * @param id - Identificador de la solicitud de ZIP. + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - downloadZipRequest(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/zip-requests/' + id + '/zip'); + downloadZipRequest( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/zip-requests/${encodeURIComponent(id)}/zip`, + { method: 'GET', datePlan: operationDatePlans.downloadInvoiceZipRequest }, + ) } - /** Gets a short-lived URL for downloading a generated invoice ZIP request. */ - downloadZipRequestUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/invoices/zip-requests/' + id + '/download-url'); + /** + * Obtener URL de descarga del ZIP mensual + * + * Devuelve un objeto con los metadatos del archivo y una URL temporal para descargar el ZIP de una solicitud terminada sin que el archivo viaje a través de tu servidor. + * + * La URL permite acceder únicamente a ese archivo mientras sea válida: trátala como una credencial y no la almacenes. Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + * + * @param id - Identificador de la solicitud de ZIP. + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadZipRequestUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'getInvoiceZipRequestDownloadUrl'> + >(`/invoices/zip-requests/${encodeURIComponent(id)}/download-url`, { + method: 'GET', + datePlan: operationDatePlans.getInvoiceZipRequestDownloadUrl, + }) } /** - * Downloads the cancellation receipt of a canceled invoice in XML format - * @param id Invoice Id - * @returns XML file in a stream (Node.js) or Blob (browser) + * Descargar acuse de cancelación + * + * Descarga en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * @param id - ID del objeto a obtener + * @returns Archivo como stream en Node.js o Blob en el navegador. */ downloadCancellationReceiptXml( id: string, - ): Promise { - return this.client.get('/invoices/' + id + '/cancellation_receipt/xml'); + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'downloadCancellationReceiptXml'> + >(`/invoices/${encodeURIComponent(id)}/cancellation_receipt/xml`, { + method: 'GET', + datePlan: operationDatePlans.downloadCancellationReceiptXml, + }) } /** - * Downloads the cancellation receipt of a canceled invoice in PDF format - * @param id Invoice Id - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Descargar acuse de cancelación + * + * Descarga en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * @param id - ID del objeto a obtener + * @returns Archivo como stream en Node.js o Blob en el navegador. */ downloadCancellationReceiptPdf( id: string, - ): Promise { - return this.client.get('/invoices/' + id + '/cancellation_receipt/pdf'); + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'downloadCancellationReceiptXml'> + >(`/invoices/${encodeURIComponent(id)}/cancellation_receipt/pdf`, { + method: 'GET', + datePlan: operationDatePlans.downloadCancellationReceiptXml, + }) } /** - * Gets a short-lived URL for downloading a cancellation receipt PDF directly. - * @param id Invoice Id - * @returns Signed download URL and its metadata + * Obtener enlace del acuse de cancelación + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. */ - downloadCancellationReceiptPdfUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get( - '/invoices/' + id + '/cancellation_receipt/download-url/pdf', - ); + downloadCancellationReceiptPdfUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'getCancellationReceiptDownloadUrl'> + >( + `/invoices/${encodeURIComponent(id)}/cancellation_receipt/download-url/pdf`, + { + method: 'GET', + datePlan: operationDatePlans.getCancellationReceiptDownloadUrl, + }, + ) } - /** Gets a short-lived URL for downloading a cancellation receipt XML file. */ - downloadCancellationReceiptXmlUrl(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get( - '/invoices/' + id + '/cancellation_receipt/download-url/xml', - ); + /** + * Obtener enlace del acuse de cancelación + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar en XML o PDF el acuse emitido por el SAT al solicitar la cancelación mediante Facturapi. El acuse contiene el resultado inmediato de la solicitud y no necesariamente acredita que el CFDI ya esté cancelado; consulta el estado de la factura para confirmar el desenlace. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadCancellationReceiptXmlUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'getCancellationReceiptDownloadUrl'> + >( + `/invoices/${encodeURIComponent(id)}/cancellation_receipt/download-url/xml`, + { + method: 'GET', + datePlan: operationDatePlans.getCancellationReceiptDownloadUrl, + }, + ) } /** - * Edits an invoice with "draft" status. - * @param id Invoice Id - * @param data Invoice data to edit - * @returns Edited invoice + * Editar borrador de factura + * + * Actualiza la información de una factura con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * En el objeto `invoice` de respuesta, Facturapi asignará automáticamente + * el campo `is_ready_to_stamp` con el valor `true` si la factura pasa la + * validación mínima requerida para ser timbrada; de lo contrario, el campo + * `is_ready_to_stamp` será `false`. + * + * @param id - ID del objeto a editar + * @param data - Datos de la solicitud. + * @returns Objeto `Invoice` editado correctamente */ - updateDraft(id: string, data: Record): Promise { - return this.client.put('/invoices/' + id, { body: data }); + updateDraft( + id: string, + data: OperationBody<'updateDraftInvoice'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}`, + { + method: 'PUT', + datePlan: operationDatePlans.updateDraftInvoice, + body: data, + }, + ) } /** - * Stamps an invoice with "draft" status. - * @param id Invoice Id - * @param params Query params - * @returns Stamped invoice + * Timbrar borrador de factura + * + * Timbra una factura con status `draft` y la envía al SAT para su validación. + * + * Al usar este método, el valor del campo `is_ready_to_stamp` (asignado por Facturapi) + * deberá ser `true`. De otra forma, la llamada regresará un error. + * + * Este método no permite editar la factura, sólo timbrarla. Si necesitas editar información + * en la factura antes de timbrarla, usa el método [Editar Borrador de Factura](https://docs.facturapi.io/api/#tag/invoice/operation/editDraftInvoice). + * + * @param id - ID del objeto a timbrar + * @param params - Parámetros de consulta. + * @returns Objeto `Invoice` timbrado correctamente */ stampDraft( id: string, - params?: Record | null, - ): Promise { - return this.client.post('/invoices/' + id + '/stamp', { params }); + params?: OperationQuery<'stampDraftInvoice'> | null, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/stamp`, + { + method: 'POST', + datePlan: operationDatePlans.stampDraftInvoice, + params: params, + }, + ) } /** - * Updates the latest status of the invoice from the SAT - * @param id Invoice Id - * @returns Updated invoice + * Actualizar status de factura + * + * Consulta el status de una factura timbrada en el SAT y actualiza el objeto invoice + * con La información más reciente. + * + * @param id - ID del objeto invoice a actualizar + * @returns Objeto `Invoice` actualizado */ - updateStatus(id: string): Promise { - return this.client.put('/invoices/' + id + '/status'); + updateStatus(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/status`, + { method: 'PUT', datePlan: operationDatePlans.updateInvoiceStatus }, + ) } /** - * Creates a draft invoice from any other invoice - * @param id Invoice Id - * @returns Draft invoice + * Copiar a borrador + * + * Crea una copia en borrador de la factura especificada. + * + * @param id - ID de la factura a copiar + * @returns Nuevo objeto `Invoice` con status `draft`. */ - copyToDraft(id: string): Promise { - return this.client.post('/invoices/' + id + '/copy'); + copyToDraft(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/invoices/${encodeURIComponent(id)}/copy`, + { method: 'POST', datePlan: operationDatePlans.copyToDraftInvoice }, + ) } /** - * Previews an invoice PDF before stamping it - * @param body Invoice data - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Vista previa de factura en PDF + * + * Genera una vista previa en PDF de una factura sin timbrar ni guardar en la organización. + * + * @param body - Datos de la solicitud. + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - previewPdf(body: Record): Promise { - return this.client.post('/invoices/preview/pdf', { body }); + previewPdf( + body: OperationBody<'previewInvoicePdf'>, + ): Promise> { + return this.client.request>( + `/invoices/preview/pdf`, + { + method: 'POST', + datePlan: operationDatePlans.previewInvoicePdf, + body: body, + }, + ) } - /** Gets a short-lived URL for an invoice PDF preview. */ - previewPdfUrl(body: Record): Promise { - return this.client.post('/invoices/preview/pdf/download-url', { body }); + /** + * Obtener URL del preview PDF de factura + * + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura sin timbrar. + * + * @param body - Datos de la solicitud. + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + previewPdfUrl( + body: OperationBody<'previewInvoicePdfUrl'>, + ): Promise> { + return this.client.request>( + `/invoices/preview/pdf/download-url`, + { + method: 'POST', + datePlan: operationDatePlans.previewInvoicePdfUrl, + body: body, + }, + ) } } diff --git a/src/resources/organizations.ts b/src/resources/organizations.ts index 56bb6c7..f1e8cec 100644 --- a/src/resources/organizations.ts +++ b/src/resources/organizations.ts @@ -1,625 +1,1047 @@ -import { WrapperClient } from '../wrapper'; +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' import type { - ApiKeys, - Organization, - OrganizationInvite, - OrganizationInviteCreateInput, - OrganizationInviteResponseInput, - OrganizationTeamRole, - OrganizationTeamRoleCreateInput, - OrganizationTeamRoleTemplate, - OrganizationTeamRoleUpdateInput, - OrganizationUserAccess, - OrganizationDefaultSeriesUpdateInput, - Series, -} from '../types/organization'; -import type { BinaryInput, NodeLikeReadableStream } from '../types'; -import { SearchResult } from '../types/common'; -import { streamToBytes } from '../utils/streamToBytes'; - -function isNodeLikeReadableStream(value: unknown): value is NodeLikeReadableStream { - return ( - typeof value === 'object' && - value !== null && - typeof (value as NodeLikeReadableStream).on === 'function' - ); -} - -function toArrayBufferUint8Array(bytes: Uint8Array): Uint8Array { - const arrayBuffer = bytes.buffer.slice( - bytes.byteOffset, - bytes.byteOffset + bytes.byteLength, - ) as ArrayBuffer; - return new Uint8Array(arrayBuffer); -} - -function toBlobPartUint8Array(bytes: Uint8Array): Uint8Array { - return toArrayBufferUint8Array(bytes); -} - -const prepareFile = async ( - file: BinaryInput, - fileType: string, -): Promise => { - if (typeof Blob === 'undefined') { - throw new Error( - 'Blob is not available in this runtime. Use Node.js 18+ or provide a Blob implementation.', - ); - } - if (file instanceof Blob) return file; - if (typeof File !== 'undefined' && file instanceof File) return file; - if (file instanceof ArrayBuffer) return new Blob([file], { type: fileType }); - if (file instanceof Uint8Array) { - return new Blob([toArrayBufferUint8Array(new Uint8Array(file))], { - type: fileType, - }); - } - - if (isNodeLikeReadableStream(file)) { - const buffer = await streamToBytes(file); - return new Blob([toBlobPartUint8Array(buffer)], { - type: fileType, - }); - } - - const type = file === null ? 'null' : typeof file; - const constructorName = ( - file && - typeof file === 'object' && - 'constructor' in file && - (file as { constructor?: { name?: string } }).constructor?.name - ) - ? ` (${(file as { constructor: { name: string } }).constructor.name})` - : ''; - throw new Error(`Unsupported file input type: ${type}${constructorName}`); -}; + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { BinaryInput } from '../types/runtime' +import { prepareFile } from '../runtime/uploads' export default class Organizations { - client: WrapperClient; - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Creates a new organization for your account - * @param data - Organization data - * @returns Organization object + * Crear organización + * + * Crea una nueva Organización que pertenecerá a tu cuenta de usuario. + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](https://docs.facturapi.io/api/#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](https://docs.facturapi.io/api/#tag/organization/operation/uploadOrganizationCertificate) + * + * + * Después de crear la organización y antes de poder emitir facturas con + * la organización, deberás de terminar de configurarla llamando a los + * métodos de [Actualizar datos fiscales](https://docs.facturapi.io/api/#tag/organization/operation/editOrganizationLegal) y + * [Subir certificados (CSD)](https://docs.facturapi.io/api/#tag/organization/operation/uploadOrganizationCertificate), + * además de firmar la Carta Manifiesto que autoriza a nuestro PAC a timbrar facturas; + * puedes hacerlo en [tu dashboard](https://dashboard.facturapi.io/settings/manifiesto) + * o en [nuestro portal público](https://www.facturapi.io/manifiesto). También puedes incrustar + * en tu solución el módulo de firma de la carta (sin logos, listo para iframe): https://www.facturapi.io/embedded/manifiesto + * + * Recuerda que los folios de tu suscripción podrán ser consumidos por + * cualquiera de las organizaciones registradas bajo tu cuenta. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Organization` creado */ - create(data: Record): Promise { - return this.client.post('/organizations', { body: data }); + create( + data: OperationBody<'createOrganization'>, + ): Promise> { + return this.client.request>( + `/organizations`, + { + method: 'POST', + datePlan: operationDatePlans.createOrganization, + body: data, + }, + ) } /** - * Gets a paginated list of organizations that belong to your account - * @param params - Search parameters - * @returns Search results object. The object contains a `data` property with the list of organizations. + * Listar organizaciones + * + * Regresa una lista paginada de todas las organizationes registradas bajo tu cuenta, o realiza una búsqueda de acuerdo a parámetros. + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ list( - params?: Record | null, - ): Promise> { - if (!params) params = {}; - return this.client.get('/organizations', { params: params }); + params?: OperationQuery<'listOrganizations'> | null, + ): Promise> { + return this.client.request>( + `/organizations`, + { + method: 'GET', + datePlan: operationDatePlans.listOrganizations, + params: params, + }, + ) } /** - * Gets a single organization object - * @param id - * @returns + * Obtener organización por ID + * + * Regresa el objeto 'Organization' relacionado al `id` especificado. + * + * @param id - ID de la organización + * @returns Objeto `Organization` */ - retrieve(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/organizations/' + id); + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getOrganization }, + ) } /** - * Updates the organization's legal information - * @param id Organization Id - * @param data - * @returns + * Editar datos fiscales + * + * Actualiza los datos fiscales de la organización. + * + * Si estás buscando cómo editar el RFC, recuerda que la propiedad + * `tax_id` se asigna automáticamente al subir los Certificados de Sello + * Digital. + * + * @param id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Objeto `Organization` modificado */ - updateLegal(id: string, data: Record): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.put('/organizations/' + id + '/legal', { body: data }); + updateLegal( + id: string, + data: OperationBody<'editOrganizationLegal'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/legal`, + { + method: 'PUT', + datePlan: operationDatePlans.editOrganizationLegal, + body: data, + }, + ) } /** - * Updates the organization's customization information - * @param id Organization Id - * @param data Customization settings - * @returns Organization object + * Editar personalización + * + * Actualiza la información relacionada con la identidad o branding de la organización. + * + * @param id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Objeto `Organization` modificado */ updateCustomization( id: string, - data: Record, - ): Promise { - return this.client.put('/organizations/' + id + '/customization', { + data: OperationBody<'editOrganizationCustomization'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'editOrganizationCustomization'> + >(`/organizations/${encodeURIComponent(id)}/customization`, { + method: 'PUT', + datePlan: operationDatePlans.editOrganizationCustomization, body: data, - }); + }) } /** - * Updates the organization's customization information - * @param id Organization Id - * @param data Receipt settings - * @returns Organization object + * Editar config. recibos + * + * Actualiza los campos enviados de la configuración de recibos de la organización. + * Para activar la generación automática de facturas globales, la organización + * debe tener contratado ese feature. + * + * @param id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Objeto `Organization` modificado */ updateReceiptSettings( id: string, - data: Record, - ): Promise { - return this.client.put('/organizations/' + id + '/receipts', { + data: OperationBody<'editOrganizationReceiptsSettings'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'editOrganizationReceiptsSettings'> + >(`/organizations/${encodeURIComponent(id)}/receipts`, { + method: 'PUT', + datePlan: operationDatePlans.editOrganizationReceiptsSettings, body: data, - }); + }) } /** - * Updates the organization's customization information - * @param id Organization Id - * @param data Domain data - * @returns Organization object + * Elegir dominio de autofactura + * + * Elige el dominio que utilizará esta organización en su micrositio de + * autofactura. Una vez elegido el dominio, deberás ponerte en contacto + * con nosotros si necesitas cambiarlo. + * + * El dominio que elijas será el que aparecerá en el campo + * `self_invoice_url` al crear un nuevo recibo, de la siguiente manera: + * + * `https://factura.space/{DOMAIN}/{RECEIPT_KEY}` + * + * @param id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Objeto `Organization` modificado */ - updateDomain(id: string, data: Record): Promise { - return this.client.put('/organizations/' + id + '/domain', { body: data }); + updateDomain( + id: string, + data: OperationBody<'editOrganizationDomain'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/domain`, + { + method: 'PUT', + datePlan: operationDatePlans.editOrganizationDomain, + body: data, + }, + ) } /** - * Checks if a domain is available for self invoices - * @param data Domain data - * @returns Domain availability + * Revisar dominio disponible + * + * Revisa si un identificador está disponible para elegir como dominio para el portal de autofactura. + * + * @param data - Parámetros de consulta. + * @returns Información de disponibilidad de dominio */ checkDomainIsAvailable( - data: Record, - ): Promise<{ available: boolean }> { - return this.client.get('/organizations/domain-check', { params: data }); + data: OperationQuery<'checkDomainAvailability'>, + ): Promise> { + return this.client.request>( + `/organizations/domain-check`, + { + method: 'GET', + datePlan: operationDatePlans.checkDomainAvailability, + params: data, + }, + ) } /** - * Uploads the organization's logo - * @param id Organization Id - * @param file Logo file - * @returns Organization object + * Subir logotipo + * + * Sube el logotipo de la organización que será colocado en el PDF y en + * los correos que se envían al cliente con la factura adjunta. + * + * El archivo debe ser una imagen en formato JPG o PNG y tener un tamaño + * no mayor a 500 KB. Las dimensiones recomendadas son 800 × 500px. + * + * Si la organización ya tiene un logotipo, esta llamada reemplaza el + * logotipo anterior. + * + * @param id - ID de la organización + * @param file - Contenido binario del archivo con la imagen que se usará como + * logotipo. Formatos soportados: + * - jpg + * - png + * - svg + * + * Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js. + * @returns Objeto `Organization` modificado */ async uploadLogo( id: string, file: BinaryInput, - ): Promise { - if (typeof FormData === 'undefined') { + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + if (typeof FormData === 'undefined') throw new Error( 'FormData is not available in this runtime. Use Node.js 18+ or provide a FormData implementation.', - ); - } - const preparedFile = await prepareFile( - file, - 'application/octet-stream', - ); - const formData = new FormData(); - formData.append('file', preparedFile, 'file'); - return this.client.put('/organizations/' + id + '/logo', { formData }); + ) + const formData = new FormData() + formData.append( + 'file', + await prepareFile(file, 'application/octet-stream'), + 'file', + ) + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/logo`, + { + method: 'PUT', + datePlan: operationDatePlans.uploadOrganizationLogo, + formData, + }, + ) } /** - * Uploads the organization's certificate (CSD) - * @param id Organization Id - * @param cerFile Certificate file - * @param keyFile Key file - * @param password Certificate password - * @returns Organization object + * Subir certificados (CSD) + * + * Sube los archivos del Certificado de Sello Digital (CSD) proporcionado + * por el SAT. Esta llamada también debe usarse para reemplazar los + * certificados existentes en caso de solicitar nuevos. + * + * Al actualizar tus certificados se leerá el RFC y asignará + * automáticamente a `legal.tax_id`. + * + * @param id - ID de la organización + * @param cerFile - Contenido binario del archivo con extensión `.cer` del certificado CSD. + * Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js. + * @param keyFile - Contenido binario del archivo con extensión `.key` del certificado CSD. + * Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js. + * @param password - Contraseña de la llave del certificado. + * @returns Objeto `Organization` modificado */ async uploadCertificate( id: string, cerFile: BinaryInput, keyFile: BinaryInput, password: string, - ): Promise { - if (typeof FormData === 'undefined') { + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + if (typeof FormData === 'undefined') throw new Error( 'FormData is not available in this runtime. Use Node.js 18+ or provide a FormData implementation.', - ); - } - const formData = new FormData(); - const [cerFileOrBlob, keyFileOrBlob] = await Promise.all([ + ) + const formData = new FormData() + const [cer, key] = await Promise.all([ prepareFile(cerFile, 'application/octet-stream'), prepareFile(keyFile, 'application/octet-stream'), - ]); - - formData.append('cer', cerFileOrBlob, 'cer.cer'); - formData.append('key', keyFileOrBlob, 'key.key'); - formData.append('password', password); - return this.client.put('/organizations/' + id + '/certificate', { + ]) + formData.append('cer', cer, 'cer.cer') + formData.append('key', key, 'key.key') + formData.append('password', password) + return this.client.request< + OperationResponse<'uploadOrganizationCertificate'> + >(`/organizations/${encodeURIComponent(id)}/certificate`, { + method: 'PUT', + datePlan: operationDatePlans.uploadOrganizationCertificate, formData, - }); + }) } /** - * Deletes the organization's certificate (CSD) - * @param id Organization Id - * @returns Organization object + * Eliminar certificados (CSD) + * + * Elimina los certificados (CSD) de tu organización. + * + * Esto no afecta a las facturas ya emitidas, pero no podrás emitir nuevas facturas hasta que subas nuevos certificados. + * + * @param id - ID de la organización + * @returns Objeto `Organization` modificado */ - deleteCertificate(id: string): Promise { - return this.client.delete('/organizations/' + id + '/certificate'); + deleteCertificate( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'deleteOrganizationCertificate'> + >(`/organizations/${encodeURIComponent(id)}/certificate`, { + method: 'DELETE', + datePlan: operationDatePlans.deleteOrganizationCertificate, + }) } /** - * Permanently removes a organization from your account. - * @param id Organization Id - * @returns Deleted organization object + * Eliminar organización + * + * Elimina la organización de tu cuenta de Facturapi. Una vez eliminada, + * ya no podrás acceder a sus recursos, tales como clientes, productos, + * facturas, recibos o retenciones. + * + * @param id - ID del objeto a eliminar + * @returns Objeto `Organization` eliminado correctamente */ - del(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.delete('/organizations/' + id); + del(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteOrganization }, + ) } /** - * Gets the test api key for an organization - * @param id Organization Id - * @returns Test api key + * Obtener Test Api Key + * + * Obtiene la llave secreta de ambiente Test de la organización. + * + * @param id - ID de la organización + * @returns Test API Key */ - getTestApiKey(id: string): Promise { - return this.client.get('/organizations/' + id + '/apikeys/test'); + getTestApiKey(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/apikeys/test`, + { method: 'GET', datePlan: operationDatePlans.getTestApiKey }, + ) } /** - * Renews the test api key and makes the previous one unusable - * @param id Organization Id - * @returns New test api key + * Renovar Test API Key + * + * Renueva la llave secreta de ambiente Test de la organización e invalida inmediatamente la anterior. + * + * @param id - ID de la organización + * @returns Test API Key */ - renewTestApiKey(id: string): Promise { - return this.client.put('/organizations/' + id + '/apikeys/test'); + renewTestApiKey(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/apikeys/test`, + { method: 'PUT', datePlan: operationDatePlans.renewTestApiKey }, + ) } /** - * List live api keys - * @param id Organization Id - * @returns List of live api keys + * Listar Live API Keys + * + * Listar llaves secretas de ambiente Live de la organización. + * + * @param id - ID de la organización + * @returns Live API Key */ - async listLiveApiKeys(id: string): Promise { - return this.client.get('/organizations/' + id + '/apikeys/live'); + listLiveApiKeys(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/apikeys/live`, + { method: 'GET', datePlan: operationDatePlans.listLiveApiKeys }, + ) } /** - * Renews the live api key and makes the previous one unusable - * @param id Organization Id - * @returns New live api key + * Crear Live API Key + * + * Genera una nueva llave secreta de ambiente Live de la organización. + * Esta operación no invalida las llaves generadas previamente. El endpoint usa `PUT` + * por compatibilidad histórica, pero su comportamiento es crear una nueva llave. + * + * @param id - ID de la organización + * @returns Live API Key */ - renewLiveApiKey(id: string): Promise { - return this.client.put('/organizations/' + id + '/apikeys/live'); + renewLiveApiKey(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/apikeys/live`, + { method: 'PUT', datePlan: operationDatePlans.renewLiveApiKey }, + ) } /** - * Delete a live api key - * @param organizationId Organization Id - * @param apiKeyId Api Key Id - * @returns List of live api keys + * Revocar Live API Key + * + * Revocar Live Api Key de tu organización. + * + * @param organizationId - ID de la organización + * @param apiKeyId - ID de la llave secreta a eliminar + * @returns Live API Key */ - async deleteLiveApiKey( + deleteLiveApiKey( organizationId: string, apiKeyId: string, - ): Promise { - return this.client.delete( - '/organizations/' + organizationId + '/apikeys/live/' + apiKeyId, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!apiKeyId) return Promise.reject(new Error('apiKeyId is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organizationId)}/apikeys/live/${encodeURIComponent(apiKeyId)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteLiveApiKey }, + ) } /** - * Get list of Series Organization - * @param organization_id Organization Id - * @returns Series object + * Listado de series + * + * Listado de series creadas para la personalización de organización. La cual lleva control de foliaje para cada tipo de factura si está asignada en las personalización de organización. + * + * @param organization_id - ID de la organización + * @returns Listado de objetos `Series` creadas previamente */ - listSeriesGroup(organization_id: string): Promise { - return this.client.get( - '/organizations/' + organization_id + '/series-group', - ); + listSeriesGroup( + organization_id: string, + ): Promise> { + if (!organization_id) + return Promise.reject(new Error('organization_id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organization_id)}/series-group`, + { method: 'GET', datePlan: operationDatePlans.getSeriesGroup }, + ) } /** - * Creates a Series Organization - * @param organization_id Organization Id - * @param seriesData - Series data - * @returns Series object + * Crear serie + * + * Crea una nueva serie de folios para la organización. + * Las series son útiles para llevar un control de los folios emitidos para cada tipo de factura. + * + * @param organization_id - ID de la organización + * @param seriesData - Datos de la solicitud. + * @returns Nuevo objeto de la `Serie` creada */ createSeriesGroup( organization_id: string, - seriesData: Series, - ): Promise { - return this.client.post( - '/organizations/' + organization_id + '/series-group', + seriesData: OperationBody<'createSeriesGroup'>, + ): Promise> { + if (!organization_id) + return Promise.reject(new Error('organization_id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organization_id)}/series-group`, { + method: 'POST', + datePlan: operationDatePlans.createSeriesGroup, body: seriesData, }, - ); + ) } /** - * Update a Series Organization - * @param organization_id Organization Id - * @param seriesName Series seriesName - * @param data - Series data - * @returns Series object + * Editar serie + * + * Edita el número de foliaje de la serie en ambientes Test y Live de la organización. + * + * @param organization_id - ID de la organización + * @param seriesName - Nombre de la serie + * @param data - Datos de la solicitud. + * @returns Objeto `Serie` editada */ updateSeriesGroup( organization_id: string, seriesName: string, - data: Pick, - ): Promise { - return this.client.put( - `/organizations/${organization_id}/series-group/${seriesName}`, + data: OperationBody<'updateSeriesGroup'>, + ): Promise> { + if (!organization_id) + return Promise.reject(new Error('organization_id is required')) + if (!seriesName) return Promise.reject(new Error('seriesName is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organization_id)}/series-group/${encodeURIComponent(seriesName)}`, { + method: 'PUT', + datePlan: operationDatePlans.updateSeriesGroup, body: data, }, - ); + ) } /** - * Sets default series for an organization - * @param organization_id Organization Id - * @param data Default series input - * @returns Organization object + * Establecer serie predeterminada + * + * Asigna una serie predeterminada para el tipo de comprobante indicado. + * + * @param organization_id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Serie predeterminada actualizada */ updateDefaultSeries( organization_id: string, - data: OrganizationDefaultSeriesUpdateInput, - ): Promise { - return this.client.put( - `/organizations/${organization_id}/series-group/default-series`, + data: OperationBody<'updateDefaultSeries'>, + ): Promise> { + if (!organization_id) + return Promise.reject(new Error('organization_id is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organization_id)}/series-group/default-series`, { + method: 'PUT', + datePlan: operationDatePlans.updateDefaultSeries, body: data, }, - ); + ) } /** - * Update a Series Organization - * @param organization_id Organization Id - * @param seriesName Series seriesName - * @returns Series object + * Eliminar serie + * + * Elimina la serie previamente creada + * + * @param organization_id - ID de la organización + * @param seriesName - Nombre de la serie + * @returns Objeto `Serie` eliminado */ deleteSeriesGroup( organization_id: string, seriesName: string, - ): Promise { - return this.client.delete( - `/organizations/${organization_id}/series-group/${seriesName}`, - ); + ): Promise> { + if (!organization_id) + return Promise.reject(new Error('organization_id is required')) + if (!seriesName) return Promise.reject(new Error('seriesName is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organization_id)}/series-group/${encodeURIComponent(seriesName)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteSeriesGroup }, + ) } /** - * Get the organization that belongs to the authenticated API key - * @returns Organization object + * Detalle de organización + * + * Retorna el detalle de la organización actualmente autenticada. + * + * @returns Objeto `Organization` */ - me(): Promise { - return this.client.get('/organizations/me'); + me(): Promise> { + return this.client.request>( + `/organizations/me`, + { method: 'GET', datePlan: operationDatePlans.meOrganization }, + ) } /** - * Updates the organization's self-invoice settings - * @param id Organization Id - * @param data Self-invoice settings - * @returns Organization object + * Editar config. autofactura + * + * Actualiza la configuración del portal de autofactura de la organización. + * + * @param id - ID de la organización + * @param data - Datos de la solicitud. + * @returns Objeto `Organization` modificado */ updateSelfInvoiceSettings( id: string, - data: Record, - ): Promise { - return this.client.put('/organizations/' + id + '/self-invoice', { + data: OperationBody<'editOrganizationSelfInvoiceSettings'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request< + OperationResponse<'editOrganizationSelfInvoiceSettings'> + >(`/organizations/${encodeURIComponent(id)}/self-invoice`, { + method: 'PUT', + datePlan: operationDatePlans.editOrganizationSelfInvoiceSettings, body: data, - }); + }) } /** - * Lists users with access to an organization. - * @param organizationId Organization Id - * @returns Array of organization access objects + * Listar usuarios con acceso a organización + * + * Regresa un arreglo con los usuarios que actualmente tienen acceso a la organización, incluyendo al propietario. Este endpoint no está paginado. + * + * @param organizationId - ID de la organización + * @returns Lista de accesos de usuarios dentro de la organización, incluyendo accesos implícitos como el del propietario */ - listTeamAccess(organizationId: string): Promise { - return this.client.get('/organizations/' + organizationId + '/team'); + listTeamAccess( + organizationId: string, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organizationId)}/team`, + { method: 'GET', datePlan: operationDatePlans.getOrganizationTeam }, + ) } /** - * Retrieves a specific user access in an organization. - * @param organizationId Organization Id - * @param accessId Access Id - * @returns Organization access object + * Obtener acceso de usuario + * + * Regresa el detalle del acceso del usuario dentro de la organización usando su `access_id`, incluyendo accesos implícitos como el del propietario. + * + * @param organizationId - ID de la organización + * @param accessId - ID del acceso + * @returns Detalle del acceso del usuario dentro de la organización, incluyendo accesos implícitos como el del propietario */ retrieveTeamAccess( organizationId: string, accessId: string, - ): Promise { - return this.client.get( - '/organizations/' + organizationId + '/team/' + accessId, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!accessId) return Promise.reject(new Error('accessId is required')) + + return this.client.request>( + `/organizations/${encodeURIComponent(organizationId)}/team/${encodeURIComponent(accessId)}`, + { method: 'GET', datePlan: operationDatePlans.getOrganizationTeamUser }, + ) } /** - * Reassigns role for a specific access in an organization. - * @param organizationId Organization Id - * @param accessId Access Id - * @param role Role Id - * @returns Updated organization access object + * Reasignar rol a usuario + * + * @param organizationId - ID de la organización + * @param accessId - ID del acceso + * @param role - role + * @returns Acceso del usuario actualizado con el nuevo rol */ updateTeamAccessRole( organizationId: string, accessId: string, - role: string, - ): Promise { - return this.client.put( - '/organizations/' + organizationId + '/team/' + accessId + '/role', + role: OperationBody<'updateOrganizationTeamUserRole'>['role'], + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!accessId) return Promise.reject(new Error('accessId is required')) + + return this.client.request< + OperationResponse<'updateOrganizationTeamUserRole'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/${encodeURIComponent(accessId)}/role`, { - body: { role }, + method: 'PUT', + datePlan: operationDatePlans.updateOrganizationTeamUserRole, + body: { role: role }, }, - ); + ) } /** - * Removes user access from an organization. - * @param organizationId Organization Id - * @param accessId Access Id - * @returns Ok response + * Eliminar usuario con acceso + * + * @param organizationId - ID de la organización + * @param accessId - ID del acceso + * @returns Usuario removido de la organización */ removeTeamAccess( organizationId: string, accessId: string, - ): Promise<{ ok: boolean }> { - return this.client.delete( - '/organizations/' + organizationId + '/team/' + accessId, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!accessId) return Promise.reject(new Error('accessId is required')) + + return this.client.request< + OperationResponse<'removeOrganizationUserAccess'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/${encodeURIComponent(accessId)}`, + { + method: 'DELETE', + datePlan: operationDatePlans.removeOrganizationUserAccess, + }, + ) } /** - * Lists invites sent from an organization. - * @param organizationId Organization Id - * @returns Array of organization invite objects + * Listar invitaciones enviadas + * + * Regresa invitaciones enviadas desde la organización. + * + * @param organizationId - ID de la organización + * @returns Lista de invitaciones enviadas y aún vigentes para la organización */ - listSentTeamInvites(organizationId: string): Promise { - return this.client.get('/organizations/' + organizationId + '/team/invites'); + listSentTeamInvites( + organizationId: string, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'listOrganizationTeamInvites'> + >(`/organizations/${encodeURIComponent(organizationId)}/team/invites`, { + method: 'GET', + datePlan: operationDatePlans.listOrganizationTeamInvites, + }) } /** - * Creates or updates an invite for an organization. - * @param organizationId Organization Id - * @param data Invite payload - * @returns Organization invite object + * Invitar usuario a organización + * + * Crea o actualiza una invitación de usuario. Por defecto, el acceso es de administrador con permisos completos; para limitarlo, crea un rol y envía su ID en `role`. + * + * Cada organización puede invitar a un usuario sin costo adicional. A partir del segundo usuario invitado, cada usuario adicional tendrá un costo mensual. Este cargo se aplica automáticamente cuando el usuario acepta la invitación. + * Puedes consultar el precio vigente en nuestra [página de precios](https://www.facturapi.io/pricing). + * + * @param organizationId - ID de la organización + * @param data - Datos de la solicitud. + * @returns Invitación creada o actualizada para el correo solicitado */ inviteUserToTeam( organizationId: string, - data: OrganizationInviteCreateInput, - ): Promise { - return this.client.post('/organizations/' + organizationId + '/team/invites', { + data: OperationBody<'createOrganizationTeamInvite'>, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'createOrganizationTeamInvite'> + >(`/organizations/${encodeURIComponent(organizationId)}/team/invites`, { + method: 'POST', + datePlan: operationDatePlans.createOrganizationTeamInvite, body: data, - }); + }) } /** - * Cancels a sent invite. - * @param organizationId Organization Id - * @param inviteKey Invite Key - * @returns Ok response + * Cancelar invitación enviada + * + * Elimina una invitación pendiente de la organización. + * + * @param organizationId - ID de la organización + * @param inviteKey - Clave pública de la invitación. + * @returns Invitación cancelada */ cancelTeamInvite( organizationId: string, inviteKey: string, - ): Promise<{ ok: boolean }> { - return this.client.delete( - '/organizations/' + organizationId + '/team/invites/' + inviteKey, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!inviteKey) return Promise.reject(new Error('inviteKey is required')) + + return this.client.request< + OperationResponse<'deleteOrganizationTeamInvite'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/invites/${encodeURIComponent(inviteKey)}`, + { + method: 'DELETE', + datePlan: operationDatePlans.deleteOrganizationTeamInvite, + }, + ) } /** - * Lists pending invites received by authenticated user. - * @returns Array of organization invite objects + * Listar invitaciones recibidas + * + * Regresa las invitaciones recibidas para el usuario autenticado. + * + * @returns Lista de invitaciones recibidas por el usuario autenticado */ - listReceivedTeamInvites(): Promise { - return this.client.get('/organizations/invites/pending'); + listReceivedTeamInvites(): Promise< + OperationResponse<'listPendingOrganizationInvites'> + > { + return this.client.request< + OperationResponse<'listPendingOrganizationInvites'> + >(`/organizations/invites/pending`, { + method: 'GET', + datePlan: operationDatePlans.listPendingOrganizationInvites, + }) } /** - * Accepts or rejects an invite. - * @param inviteKey Invite Key - * @param data Invite response payload - * @returns Ok response + * Responder invitación + * + * Acepta o rechaza una invitación usando su `invite_key`. + * + * @param inviteKey - Clave pública de la invitación. + * @param data - Datos de la solicitud. + * @returns Invitación aceptada o rechazada exitosamente */ respondTeamInvite( inviteKey: string, - data: OrganizationInviteResponseInput, - ): Promise<{ ok: boolean }> { - return this.client.post('/organizations/invites/' + inviteKey + '/response', { - body: data, - }); + data: OperationBody<'respondOrganizationInvite'>, + ): Promise> { + if (!inviteKey) return Promise.reject(new Error('inviteKey is required')) + + return this.client.request>( + `/organizations/invites/${encodeURIComponent(inviteKey)}/response`, + { + method: 'POST', + datePlan: operationDatePlans.respondOrganizationInvite, + body: data, + }, + ) } /** - * Lists organization roles. - * @param organizationId Organization Id - * @returns Array of organization role objects + * Listar roles de organización + * + * @param organizationId - ID de la organización + * @returns Lista de roles */ - listTeamRoles(organizationId: string): Promise { - return this.client.get('/organizations/' + organizationId + '/team/roles'); + listTeamRoles( + organizationId: string, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'listOrganizationPermissionRoles'> + >(`/organizations/${encodeURIComponent(organizationId)}/team/roles`, { + method: 'GET', + datePlan: operationDatePlans.listOrganizationPermissionRoles, + }) } /** - * Lists role templates for organization scope. - * @param organizationId Organization Id - * @returns Array of organization role templates + * Listar plantillas de roles + * + * @param organizationId - ID de la organización + * @returns Plantillas disponibles */ listTeamRoleTemplates( organizationId: string, - ): Promise { - return this.client.get( - '/organizations/' + organizationId + '/team/roles/templates', - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'listOrganizationPermissionRoleTemplates'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/roles/templates`, + { + method: 'GET', + datePlan: operationDatePlans.listOrganizationPermissionRoleTemplates, + }, + ) } /** - * Lists available operation codes for organization roles. - * @param organizationId Organization Id - * @returns Array of operation codes + * Listar operaciones de permisos + * + * @param organizationId - ID de la organización + * @returns Lista de códigos de operación */ - listTeamRoleOperations(organizationId: string): Promise { - return this.client.get( - '/organizations/' + organizationId + '/team/roles/operations', - ); + listTeamRoleOperations( + organizationId: string, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'listOrganizationPermissionOperations'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/roles/operations`, + { + method: 'GET', + datePlan: operationDatePlans.listOrganizationPermissionOperations, + }, + ) } /** - * Retrieves an organization role. - * @param organizationId Organization Id - * @param roleId Role Id - * @returns Organization role object + * Obtener rol de organización + * + * @param organizationId - ID de la organización + * @param roleId - ID del rol + * @returns Detalle del rol */ retrieveTeamRole( organizationId: string, roleId: string, - ): Promise { - return this.client.get( - '/organizations/' + organizationId + '/team/roles/' + roleId, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!roleId) return Promise.reject(new Error('roleId is required')) + + return this.client.request< + OperationResponse<'getOrganizationPermissionRole'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/roles/${encodeURIComponent(roleId)}`, + { + method: 'GET', + datePlan: operationDatePlans.getOrganizationPermissionRole, + }, + ) } /** - * Creates an organization role. - * @param organizationId Organization Id - * @param data Role payload - * @returns Organization role object + * Crear rol de organización + * + * @param organizationId - ID de la organización + * @param data - Datos de la solicitud. + * @returns Rol creado */ createTeamRole( organizationId: string, - data: OrganizationTeamRoleCreateInput, - ): Promise { - return this.client.post('/organizations/' + organizationId + '/team/roles', { + data: OperationBody<'createOrganizationPermissionRole'>, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + + return this.client.request< + OperationResponse<'createOrganizationPermissionRole'> + >(`/organizations/${encodeURIComponent(organizationId)}/team/roles`, { + method: 'POST', + datePlan: operationDatePlans.createOrganizationPermissionRole, body: data, - }); + }) } /** - * Updates an organization role. - * @param organizationId Organization Id - * @param roleId Role Id - * @param data Role payload - * @returns Organization role object + * Actualizar rol de organización + * + * @param organizationId - ID de la organización + * @param roleId - ID del rol + * @param data - Datos de la solicitud. + * @returns Rol actualizado */ updateTeamRole( organizationId: string, roleId: string, - data: OrganizationTeamRoleUpdateInput, - ): Promise { - return this.client.put( - '/organizations/' + organizationId + '/team/roles/' + roleId, + data: OperationBody<'updateOrganizationPermissionRole'>, + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!roleId) return Promise.reject(new Error('roleId is required')) + + return this.client.request< + OperationResponse<'updateOrganizationPermissionRole'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/roles/${encodeURIComponent(roleId)}`, { + method: 'PUT', + datePlan: operationDatePlans.updateOrganizationPermissionRole, body: data, }, - ); + ) } /** - * Deletes an organization role. - * @param organizationId Organization Id - * @param roleId Role Id - * @returns Ok response + * Eliminar rol de organización + * + * @param organizationId - ID de la organización + * @param roleId - ID del rol + * @returns Rol eliminado */ deleteTeamRole( organizationId: string, roleId: string, - ): Promise<{ ok: boolean }> { - return this.client.delete( - '/organizations/' + organizationId + '/team/roles/' + roleId, - ); + ): Promise> { + if (!organizationId) + return Promise.reject(new Error('organizationId is required')) + if (!roleId) return Promise.reject(new Error('roleId is required')) + + return this.client.request< + OperationResponse<'deleteOrganizationPermissionRole'> + >( + `/organizations/${encodeURIComponent(organizationId)}/team/roles/${encodeURIComponent(roleId)}`, + { + method: 'DELETE', + datePlan: operationDatePlans.deleteOrganizationPermissionRole, + }, + ) + } + + /** + * Subir certificado FIEL + * + * Sube los archivos de la e.firma (FIEL) de la organización. + * + * La e.firma (FIEL) no es necesaria para crear CFDI. Para timbrar CFDI + * solo necesitas cargar el Certificado de Sello Digital (CSD). La FIEL es + * necesaria para utilizar la descarga masiva de CFDI. + * + * @param id - ID de la organización. También puedes usar `me` con la Live Secret Key de la organización. + * @param cerFile - Contenido binario del archivo con extensión `.cer` de la e.firma (FIEL). + * Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js. + * @param keyFile - Contenido binario del archivo con extensión `.key` de la e.firma (FIEL). + * Acepta Blob, File, ArrayBuffer, Uint8Array o un stream de Node.js. + * @param password - Contraseña de la llave privada de la e.firma (FIEL). + * @returns Objeto `Organization` modificado + */ + async uploadFiel( + id: string, + cerFile: BinaryInput, + keyFile: BinaryInput, + password: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + if (typeof FormData === 'undefined') + throw new Error( + 'FormData is not available in this runtime. Use Node.js 18+ or provide a FormData implementation.', + ) + const formData = new FormData() + const [cer, key] = await Promise.all([ + prepareFile(cerFile, 'application/octet-stream'), + prepareFile(keyFile, 'application/octet-stream'), + ]) + formData.append('cer', cer, 'cer.cer') + formData.append('key', key, 'key.key') + formData.append('password', password) + return this.client.request>( + `/organizations/${encodeURIComponent(id)}/fiel`, + { + method: 'PUT', + datePlan: operationDatePlans.uploadOrganizationFiel, + formData, + }, + ) } } diff --git a/src/resources/products.ts b/src/resources/products.ts index e20afa5..3951ac3 100644 --- a/src/resources/products.ts +++ b/src/resources/products.ts @@ -1,59 +1,109 @@ -import { - Product, - SearchResult -} from '../types'; -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' export default class Products { - client: WrapperClient; - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Creates a new product in your organization - * @param data - Product data - * @returns Product object + * Crear producto + * + * Registra un nuevo producto o servicio en tu catálogo de Facturapi. + * + * Puedes usar el ID del producto para crear facturas sin tener que enviar todos los datos del producto cada vez. + * + * Ten en cuenta que los productos que crees en ambiente _Test_ **no se + * comparten** con el ambiente _Live_. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Product` creado */ - create(data: Record): Promise { - return this.client.post('/products', { body: data }); + create( + data: OperationBody<'createProduct'>, + ): Promise> { + return this.client.request>( + `/products`, + { + method: 'POST', + datePlan: operationDatePlans.createProduct, + body: data, + }, + ) } /** - * Gets a paginated list of products that belong to your organization - * @param params - Search parameters - * @returns Search results object. The object contains a `data` property with the list of products. + * Listar productos + * + * Regresa una lista paginada de todos los productos de una organización o realiza una búsqueda de acuerdo a parámetros + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - list(params?: Record | null): Promise> { - return this.client.get('/products', { params: params }); + list( + params?: OperationQuery<'listProducts'> | null, + ): Promise> { + return this.client.request>(`/products`, { + method: 'GET', + datePlan: operationDatePlans.listProducts, + params: params, + }) } /** - * Gets a single product object - * @param id - Product Id - * @returns Product object + * Obtener producto por ID + * + * Regresa el objeto `Product` relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Product` */ - retrieve(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/products/' + id); + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/products/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getProduct }, + ) } /** - * Updates a product - * @param id - Product Id - * @param data - Product data to update - * @returns Updated product + * Editar producto + * + * Actualiza la información de un producto existente, asignando los valores de los parámetros enviados. Los parámetros que no se envíen en la petición no se modificarán. + * + * @param id - ID del objeto a editar + * @param data - Datos de la solicitud. + * @returns Objeto `Product` editado correctamente */ - update(id: string, data: Record): Promise { - return this.client.put('/products/' + id, { body: data }); + update( + id: string, + data: OperationBody<'editProduct'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/products/${encodeURIComponent(id)}`, + { method: 'PUT', datePlan: operationDatePlans.editProduct, body: data }, + ) } /** - * Permanently removes a product from your organization. - * @param id - Product Id - * @returns Deleted product + * Eliminar producto + * + * Elimina el producto de tu organización. Las facturas asociadas al producto **no** se eliminarán. + * + * @param id - ID del objeto a eliminar + * @returns Objeto `Product` eliminado correctamente */ - del(id: string): Promise { - return this.client.delete('/products/' + id); + del(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/products/${encodeURIComponent(id)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteProduct }, + ) } } diff --git a/src/resources/receipts.ts b/src/resources/receipts.ts index 122e03e..0caafc5 100644 --- a/src/resources/receipts.ts +++ b/src/resources/receipts.ts @@ -1,142 +1,374 @@ -import { - BinaryDownload, - GenericResponse, - Invoice, - ReceiptsToInvoiceInput, - Receipt, - SearchResult, - SendEmailBody, - SignedDownloadUrl, - PreviewReceiptsToInvoicePdfInput, -} from '../types' -import { WrapperClient } from '../wrapper' - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { components as OutputComponents } from '../generated/output' export default class Receipts { - client: WrapperClient - constructor(client: WrapperClient) { - this.client = client + constructor(public client: WrapperClient) {} + /** + * Crear recibo + * + * Crea un nuevo Recibo, el cual funge como nota de venta. + * + * Todos los recibos generan una URL de autofactura que cliente puede + * visitar para llenar sus datos fiscales en un micrositio con el branding + * de la organización. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Receipt` creado + */ + create( + data: OperationBody<'createReceipt'>, + ): Promise> { + return this.client.request>( + `/receipts`, + { + method: 'POST', + datePlan: operationDatePlans.createReceipt, + body: data, + }, + ) } /** - * Creates a new receipt - * @param data Receipt data - * @returns Receipt object + * Listar recibos + * + * Regresa una lista paginada de todos los recibos de una organización o realiza una búsqueda de acuerdo a parámetros + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - create(data: Record): Promise { - return this.client.post('/receipts', { body: data }) + list( + params?: OperationQuery<'listReceipts'> | null, + ): Promise> { + return this.client.request>(`/receipts`, { + method: 'GET', + datePlan: operationDatePlans.listReceipts, + params: params, + }) } /** - * Gets a paginated list of receipts that belong to your organization - * @param params Search parameters - * @returns Search results object. The object contains a `data` property with the list of receipts. + * Obtener recibo por ID + * + * Regresa el objeto 'Receipt' relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Receipt` */ - list(params?: Record | null): Promise> { - if (!params) params = {} - return this.client.get('/receipts', { params }) + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getReceipt }, + ) } /** - * Gets a single receipt object - * @param id Receipt Id - * @returns Receipt object + * Facturar recibo + * + * Crea una factura a partir de un recibo. + * + * Sólo pueden facturarse recibos abiertos (`status = "open"`) + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado al recibo. Si omites `customer`, el + * recibo debe tener un cliente asignado previamente. + * + * Una vez facturado, el `status` del recibo cambiará a `"invoiced_to_customer"`. + * + * @param id - ID del recibo a facturar + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Invoice` creado */ - retrieve(id: string): Promise { + invoice( + id: string, + data: OperationBody<'invoiceReceipt'>, + ): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/receipts/' + id) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}/invoice`, + { + method: 'POST', + datePlan: operationDatePlans.invoiceReceipt, + body: data, + }, + ) } /** - * Creates an invoice for this receipt - * @param id Receipt Id - * @param data Invoice data - * @returns Invoice object + * Crear factura global + * + * Crea una factura global que incluirá todos los recibos con `status = “open”` de un cierto periodo. + * + * La factura global se emite al cliente genérico `PUBLICO EN GENERAL`. + * Los recibos incluidos quedan asociados a ese cliente y su `status` + * cambia a `"invoiced_globally"`. + * + * Una factura global puede incluir hasta 5,000 recibos abiertos. Si el periodo + * contiene más, puedes enviar `limit_to_max_receipts: true` y repetir la solicitud + * con el mismo periodo hasta recibir `null`. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Invoice` creado, o `null` si no hay recibos abiertos en el periodo */ - invoice(id: string, data: Record): Promise { - return this.client.post('/receipts/' + id + '/invoice', { body: data }) + createGlobalInvoice( + data: OperationBody<'createGlobalInvoice'>, + ): Promise> { + return this.client.request>( + `/receipts/global-invoice`, + { + method: 'POST', + datePlan: operationDatePlans.createGlobalInvoice, + body: data, + }, + ) } /** - * Creates a global invoice for open receipts - * @param data - * @returns + * Facturar múltiples recibos + * + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + * + * @param data - Datos de la solicitud. + * @returns Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` */ - createGlobalInvoice(data: Record): Promise { - return this.client.post('/receipts/global-invoice', { body: data }) - } + toInvoice( + data: OperationBody<'createToInvoiceFromReceipts'> & { dry_run: true }, + ): Promise + + /** + * Facturar múltiples recibos + * + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + * + * @param data - Datos de la solicitud. + * @returns Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` + */ + toInvoice( + data: OperationBody<'createToInvoiceFromReceipts'> & { dry_run?: false }, + ): Promise + + /** + * Facturar múltiples recibos + * + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + * + * @param data - Datos de la solicitud. + * @returns Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` + */ + toInvoice( + data: OperationBody<'createToInvoiceFromReceipts'>, + ): Promise> /** - * Creates an invoice from multiple receipts by key. - * Supports dry-run summaries when `dry_run` is true. - * @param data Receipts to-invoice request data - * @returns Invoice object or dry-run summary + * Facturar múltiples recibos + * + * Crea una sola factura a partir de múltiples recibos seleccionados por su `key`. + * + * Si envías `customer`, ese cliente se usará como receptor de la factura y + * sobrescribirá el cliente asignado a los recibos incluidos. Si omites + * `customer`, todos los recibos deben tener asignado el mismo cliente. + * También se validará el campo `address` de los recibos incluidos. + * + * Si `dry_run` es `true`, no crea la factura y regresa un resumen de vista previa. + * El `dry_run` valida las mismas reglas que la creación real, pero no persiste cambios. + * + * @param data - Datos de la solicitud. + * @returns Objeto `Invoice` creado u objeto resumen cuando `dry_run=true` */ - toInvoice(data: ReceiptsToInvoiceInput): Promise { - return this.client.post('/receipts/to-invoice', { body: data }) + toInvoice( + data: OperationBody<'createToInvoiceFromReceipts'>, + ): Promise> { + return this.client.request< + OperationResponse<'createToInvoiceFromReceipts'> + >(`/receipts/to-invoice`, { + method: 'POST', + datePlan: operationDatePlans.createToInvoiceFromReceipts, + body: data, + }) } /** - * Generates a PDF preview for a receipts-to-invoice request before stamping. - * @param data Receipts-to-invoice preview data - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Vista previa PDF de factura múltiple + * + * Genera una vista previa en PDF para una factura construida a partir de múltiples recibos seleccionados por `key`. + * + * La vista previa valida las mismas reglas de cliente que la creación real: + * si omites `customer`, todos los recibos deben tener asignado el mismo cliente. + * + * @param data - Datos de la solicitud. + * @returns Archivo como stream en Node.js o Blob en el navegador. */ previewToInvoicePdf( - data: PreviewReceiptsToInvoicePdfInput, - ): Promise { - return this.client.post('/receipts/to-invoice/preview', { + data: OperationBody<'previewToInvoiceFromReceipts'>, + ): Promise> { + return this.client.request< + OperationResponse<'previewToInvoiceFromReceipts'> + >(`/receipts/to-invoice/preview`, { + method: 'POST', + datePlan: operationDatePlans.previewToInvoiceFromReceipts, body: data, }) } - /** Gets a short-lived URL for a receipts-to-invoice PDF preview. */ + /** + * Obtener URL del preview de factura de recibos + * + * Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura construida con los recibos seleccionados. + * + * @param data - Datos de la solicitud. + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ previewToInvoicePdfUrl( - data: PreviewReceiptsToInvoicePdfInput, - ): Promise { - return this.client.post('/receipts/to-invoice/preview/download-url', { + data: OperationBody<'previewToInvoiceFromReceiptsUrl'>, + ): Promise> { + return this.client.request< + OperationResponse<'previewToInvoiceFromReceiptsUrl'> + >(`/receipts/to-invoice/preview/download-url`, { + method: 'POST', + datePlan: operationDatePlans.previewToInvoiceFromReceiptsUrl, body: data, }) } /** - * Marks a receipt as canceled. The receipt won't be available for invoicing anymore. - * @param id - * @returns + * Cancelar recibo + * + * Marca un recibo como cancelado, cambiando su propiedad `status` a `"canceled"`. + * + * Una vez cancelado, el recibo no podrá ser facturado. + * + * @param id - ID del recibo a cancelar + * @returns Objeto 'Receipt' cancelado exitosamente + */ + cancel(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}`, + { method: 'DELETE', datePlan: operationDatePlans.cancelReceipt }, + ) + } + + /** + * Enviar recibo por correo electrónico + * + * Envía un correo electrónico a la dirección de tu cliente. + * + * El correo enviado estará personalizado con el logotipo y los colores de la organización que lo creó, + * e incluirá un botón para facturar el recibo, así con el recibo en formato PDF adjunto al mensaje. + * + * @param id - ID del objeto a obtener + * @param data - Datos de la solicitud. + * @returns Objeto genérico de respuesta */ - cancel(id: string): Promise { - return this.client.delete('/receipts/' + id) + sendByEmail( + id: string, + data?: OperationBody<'sendReceiptByEmail'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}/email`, + { + method: 'POST', + datePlan: operationDatePlans.sendReceiptByEmail, + body: data, + }, + ) } /** - * Sends the receipt to the customer's email - * @param id Receipt Id - * @param data Additional arguments - * @param data.email Email address to send the receipt to - * @returns Email sent confirmation + * Descargar PDF + * + * Descarga el recibo digital en formato PDF. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - sendByEmail(id: string, data?: SendEmailBody): Promise { - return this.client.post('/receipts/' + id + '/email', { body: data }) + downloadPdf(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}/pdf`, + { method: 'GET', datePlan: operationDatePlans.downloadReceiptPdf }, + ) } /** - * Downloads the specified receipt in PDF format - * @param id Receipt Id - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar el recibo digital en PDF, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. */ - downloadPdf(id: string): Promise { - return this.client.get('/receipts/' + id + '/pdf') + downloadPdfUrl( + id: string, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}/download-url/pdf`, + { method: 'GET', datePlan: operationDatePlans.getReceiptDownloadUrl }, + ) } /** - * Gets a short-lived URL for downloading the receipt PDF directly, instead of - * streaming the file through the SDK. + * Asignar o reasignar cliente a recibo * - * A receipt is a nota de venta and is not stamped, so the PDF is the only - * representation there is to download. - * @param id Receipt Id - * @returns Signed download URL and its metadata + * Asigna o reasigna un cliente existente (por ID) a un recibo, o crea uno nuevo enviando el objeto del cliente. + * + * @param id - ID del recibo a actualizar + * @param data - Datos de la solicitud. + * @returns Objeto `Receipt` actualizado */ - downloadPdfUrl(id: string): Promise { + updateCustomer( + id: string, + data: OperationBody<'assignReceiptCustomer'>, + ): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/receipts/' + id + '/download-url/pdf') + + return this.client.request>( + `/receipts/${encodeURIComponent(id)}`, + { + method: 'PUT', + datePlan: operationDatePlans.assignReceiptCustomer, + body: data, + }, + ) } } diff --git a/src/resources/retentions.ts b/src/resources/retentions.ts index 81e0e86..6cdd102 100644 --- a/src/resources/retentions.ts +++ b/src/resources/retentions.ts @@ -1,144 +1,330 @@ -import { - BinaryDownload, - GenericResponse, - Retention, - SearchResult, - SendEmailBody, - SignedDownloadUrl, -} from '../types' -import { WrapperClient } from '../wrapper' - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { components as InputComponents } from '../generated/input' export default class Retentions { - client: WrapperClient - constructor(client: WrapperClient) { - this.client = client - } - + constructor(public client: WrapperClient) {} /** - * Creates a new valid retention (CFDI). - * @param data - * @returns + * Crear retención + * + * Crea una nueva Retención. Si el comprobante es creado en ambiente Live, ésta será **timbrado y enviado al SAT**. + * + * Para crear una retención en borrador, envía `status: "draft"`. En ese caso, + * la retención se guardará sin timbrarse, no se enviará al PAC y podrá estar + * incompleta. Facturapi asignará `is_ready_to_stamp: true` únicamente cuando + * el borrador tenga todos los datos requeridos para timbrarse. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Retention` creado */ - create(data: Record): Promise { - return this.client.post('/retentions', { body: data }) + create( + data: OperationBody<'createRetention'>, + ): Promise> { + return this.client.request>( + `/retentions`, + { + method: 'POST', + datePlan: operationDatePlans.createRetention, + body: data, + }, + ) } /** - * Gets a paginated list of retentions created by the organization - * @param params - Search parameters - * @returns + * Listar retenciones + * + * Regresa una lista paginada de todas las retenciones de una organización o realiza una búsqueda de acuerdo a parámetros + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - list(params?: Record | null): Promise> { - if (!params) params = {} - return this.client.get('/retentions', { params }) + list( + params?: OperationQuery<'listRetentions'> | null, + ): Promise> { + return this.client.request>( + `/retentions`, + { + method: 'GET', + datePlan: operationDatePlans.listRetentions, + params: params, + }, + ) } /** - * Gets a single retention object - * @param id - * @returns + * Obtener retención por ID + * + * Regresa el objeto 'Retention' relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Retention` */ - retrieve(id: string): Promise { + retrieve(id: string): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/retentions/' + id) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getRetention }, + ) } /** - * Cancels a retention. - * @param id - * @param params - Optional cancellation parameters (e.g., motive, substitution) - * @returns + * Cancelar retención + * + * Realiza una solicitud de cancelación de retención ante el SAT. + * + * A diferencia de las facturas comunes, la cancelación de la retención es inmediata y no requiere autorización de parte del receptor. + * + * Si el status de la retención es `draft`, este método la eliminará de la + * base de datos sin llamar al SAT/PAC y sin requerir parámetros de cancelación. + * + * @param id - ID de la retención a cancelar + * @param params - Parámetros de consulta. + * @param params.motive - Clave que representa el motivo de la cancelación de la retención. + * Requerido para retenciones que no son borrador. + * - `01`: **Comprobante emitido con errores con relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y ya + * se ha emitido el comprobante que la sustituye, el cual deberá indicarse por medio + * del atributo `substitution`. + * - `02`: **Comprobante emitido con errores sin relación**. Cuando la + * retención contiene algún error en las cantidades, claves o cualquier otro dato y no + * se requiere relacionar con otra retención. + * - `03`: **No se llevó a cabo la operación**. Cuando la operación o transacción no se concretó. + * - `04`: **Operación nominativa relacionada en la retención global**. Cuando se requiere cancelar + * una retención al público en general porque el cliente solicita su comprobante. + * + * @param params.substitution - ID de la retención que sustituye a la retención que se está cancelando + * Puedes usar el ID de Facturapi o el folio fiscal (UUID). + * Requerido para los motivos 01 y 04. Eliminar un borrador no requiere parámetros de consulta. + * + * @returns Objeto `Retention` cancelado exitosamente */ - cancel(id: string, params?: Record): Promise { - return this.client.delete('/retentions/' + id, { params }) + cancel( + id: string, + params?: InputComponents['schemas']['CancellationQueryInput'], + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}`, + { + method: 'DELETE', + datePlan: operationDatePlans.cancelRetention, + params: params, + }, + ) } /** - * Edits a retention with "draft" status. - * @param id Retention Id - * @param data Retention data to edit - * @returns Edited retention + * Editar borrador de retención + * + * Actualiza la información de una retención con status `draft`, asignando + * los valores de los parámetros enviados. Los parámetros que no se envíen + * en la petición no se modificarán. + * + * Facturapi recalculará automáticamente `is_ready_to_stamp` después de cada + * edición. Si la retención ya no está en status `draft`, la llamada regresará + * un error. + * + * @param id - ID de la retención a editar + * @param data - Datos de la solicitud. + * @returns Objeto `Retention` editado correctamente */ - updateDraft(id: string, data: Record): Promise { - return this.client.put('/retentions/' + id, { body: data }) + updateDraft( + id: string, + data: OperationBody<'updateDraftRetention'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}`, + { + method: 'PUT', + datePlan: operationDatePlans.updateDraftRetention, + body: data, + }, + ) } /** - * Stamps a retention with "draft" status. - * @param id Retention Id - * @returns Stamped retention + * Timbrar borrador de retención + * + * Timbra una retención con status `draft` y la envía al SAT para su validación. + * + * Facturapi validará el borrador como una retención completa antes de timbrarlo. + * Si el borrador está incompleto o no es válido, la llamada regresará un error. + * + * @param id - ID de la retención a timbrar + * @returns Objeto `Retention` timbrado correctamente */ - stampDraft(id: string): Promise { - return this.client.post('/retentions/' + id + '/stamp') + stampDraft(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/stamp`, + { method: 'POST', datePlan: operationDatePlans.stampDraftRetention }, + ) } /** - * Creates a draft retention from any other retention. - * @param id Retention Id - * @returns Draft retention + * Copiar a borrador + * + * Crea una copia en borrador de la retención especificada. La copia no conserva + * campos propios del timbrado, cancelación, idempotencia o identidad externa. + * + * @param id - ID de la retención a copiar + * @returns Nuevo objeto `Retention` con status `draft`. */ - copyToDraft(id: string): Promise { - return this.client.post('/retentions/' + id + '/copy') + copyToDraft(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/copy`, + { method: 'POST', datePlan: operationDatePlans.copyToDraftRetention }, + ) } /** - * Sends a retention to the customer's email - * @param id Retention Id - * @param data Additional arguments - * @param data.email Email address to send the retention to - * @returns + * Enviar retención por correo electrónico + * + * Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + * + * @param id - ID del objeto a obtener + * @param data - Datos de la solicitud. + * @returns Objeto genérico de respuesta */ - sendByEmail(id: string, data?: SendEmailBody): Promise { - return this.client.post('/retentions/' + id + '/email', { body: data }) + sendByEmail( + id: string, + data?: OperationBody<'sendRetentionByEmail'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/email`, + { + method: 'POST', + datePlan: operationDatePlans.sendRetentionByEmail, + body: data, + }, + ) } /** - * Downloads the specified retention in PDF format - * @param id Retention Id - * @returns PDF file in a stream (Node.js) or Blob (browser) + * Descargar retención + * + * Descarga una retención en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - downloadPdf(id: string): Promise { - return this.client.get('/retentions/' + id + '/pdf') + downloadPdf(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/pdf`, + { method: 'GET', datePlan: operationDatePlans.downloadRetention }, + ) } /** - * Downloads the specified retention in XML format - * @param id Retention Id - * @returns XML file in a stream (Node.js) or Blob (browser) + * Descargar retención + * + * Descarga una retención en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - downloadXml(id: string): Promise { - return this.client.get('/retentions/' + id + '/xml') + downloadXml(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/xml`, + { method: 'GET', datePlan: operationDatePlans.downloadRetention }, + ) } /** - * Downloads the specified retention in a ZIP package containing both PDF and XML files - * @param id Retention Id - * @returns ZIP file in a stream (Node.js) or Blob (browser) + * Descargar retención + * + * Descarga una retención en PDF, XML o ambos en un archivo comprimido ZIP. + * + * @param id - ID del objeto a descargar + * @returns Archivo como stream en Node.js o Blob en el navegador. */ - downloadZip(id: string): Promise { - return this.client.get('/retentions/' + id + '/zip') + downloadZip(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/zip`, + { method: 'GET', datePlan: operationDatePlans.downloadRetention }, + ) } /** - * Gets a short-lived URL for downloading the retention PDF, instead of - * streaming the file through the SDK. - * @param id Retention Id - * @returns Signed download URL and its metadata + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la retención en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. */ - downloadPdfUrl(id: string): Promise { + downloadPdfUrl( + id: string, + ): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/retentions/' + id + '/download-url/pdf') + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/download-url/pdf`, + { method: 'GET', datePlan: operationDatePlans.getRetentionDownloadUrl }, + ) } - /** Gets a short-lived URL for downloading a retention XML file. */ - downloadXmlUrl(id: string): Promise { + /** + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la retención en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadXmlUrl( + id: string, + ): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/retentions/' + id + '/download-url/xml') + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/download-url/xml`, + { method: 'GET', datePlan: operationDatePlans.getRetentionDownloadUrl }, + ) } - /** Gets a short-lived URL for downloading a retention ZIP file. */ - downloadZipUrl(id: string): Promise { + /** + * Obtener enlace de descarga + * + * Devuelve un objeto con los metadatos del archivo y un enlace temporal para descargar la retención en PDF, XML o ambos en un archivo comprimido ZIP, sin que el archivo pase por tu servidor. + * + * El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + * + * @param id - ID del objeto a descargar + * @returns Objeto SignedDownloadUrl con url, expires_at, content_type y filename. + */ + downloadZipUrl( + id: string, + ): Promise> { if (!id) return Promise.reject(new Error('id is required')) - return this.client.get('/retentions/' + id + '/download-url/zip') + + return this.client.request>( + `/retentions/${encodeURIComponent(id)}/download-url/zip`, + { method: 'GET', datePlan: operationDatePlans.getRetentionDownloadUrl }, + ) } } diff --git a/src/runtime/dates.ts b/src/runtime/dates.ts new file mode 100644 index 0000000..874e431 --- /dev/null +++ b/src/runtime/dates.ts @@ -0,0 +1,65 @@ +import { datePlans } from '../generated/dates' + +export type DatePlan = + | { kind: 'none' | 'date' | 'date-time' } + | { kind: 'object'; properties: Record; additional?: number } + | { kind: 'array'; items: number } + | { + kind: 'union' + variants: { plan: number; match: Record }[] + } + +const isoDate = + /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2}))?$/ + +export function deserializeResponseDates(value: unknown, planId = 0): unknown { + const plan: DatePlan = datePlans[planId] + if (!plan || !value || value instanceof Date) return value + if (plan.kind === 'date' || plan.kind === 'date-time') { + if (typeof value !== 'string' || !isoDate.test(value)) return value + if (plan.kind === 'date-time' && !value.includes('T')) return value + const date = new Date(value) + return Number.isNaN(date.getTime()) ? value : date + } + if (plan.kind === 'array') { + return Array.isArray(value) + ? value.map((item) => deserializeResponseDates(item, plan.items)) + : value + } + if (typeof value !== 'object' || Array.isArray(value)) return value + if (plan.kind === 'union') { + // Prefer constrained variants (e.g. type=pago) before an opaque custom + // complement. Unrecognized custom objects keep their original contents. + const variant = + plan.variants.find( + (variant) => + Object.keys(variant.match).length && + Object.entries(variant.match).every( + ([key, allowed]) => + key in value && allowed.includes(Reflect.get(value, key)), + ), + ) || plan.variants.find((variant) => !Object.keys(variant.match).length) + return variant ? deserializeResponseDates(value, variant.plan) : value + } + if (plan.kind === 'object') { + for (const [key, child] of Object.entries(plan.properties)) { + if (Object.prototype.hasOwnProperty.call(value, key)) + Reflect.set( + value, + key, + deserializeResponseDates(Reflect.get(value, key), child), + ) + } + if (plan.additional) { + for (const key of Object.keys(value)) { + if (!Object.prototype.hasOwnProperty.call(plan.properties, key)) + Reflect.set( + value, + key, + deserializeResponseDates(Reflect.get(value, key), plan.additional), + ) + } + } + } + return value +} diff --git a/src/runtime/uploads.ts b/src/runtime/uploads.ts new file mode 100644 index 0000000..75da537 --- /dev/null +++ b/src/runtime/uploads.ts @@ -0,0 +1,60 @@ +import type { BinaryInput, NodeLikeReadableStream } from '../types' +import { streamToBytes } from '../utils/streamToBytes' + +function isNodeLikeReadableStream( + value: unknown, +): value is NodeLikeReadableStream { + return ( + typeof value === 'object' && + value !== null && + typeof (value as NodeLikeReadableStream).on === 'function' + ) +} + +function toArrayBufferUint8Array(bytes: Uint8Array): Uint8Array { + const arrayBuffer = bytes.buffer.slice( + bytes.byteOffset, + bytes.byteOffset + bytes.byteLength, + ) as ArrayBuffer + return new Uint8Array(arrayBuffer) +} + +function toBlobPartUint8Array(bytes: Uint8Array): Uint8Array { + return toArrayBufferUint8Array(bytes) +} + +export const prepareFile = async ( + file: BinaryInput, + fileType: string, +): Promise => { + if (typeof Blob === 'undefined') { + throw new Error( + 'Blob is not available in this runtime. Use Node.js 18+ or provide a Blob implementation.', + ) + } + if (file instanceof Blob) return file + if (typeof File !== 'undefined' && file instanceof File) return file + if (file instanceof ArrayBuffer) return new Blob([file], { type: fileType }) + if (file instanceof Uint8Array) { + return new Blob([toArrayBufferUint8Array(new Uint8Array(file))], { + type: fileType, + }) + } + + if (isNodeLikeReadableStream(file)) { + const buffer = await streamToBytes(file) + return new Blob([toBlobPartUint8Array(buffer)], { + type: fileType, + }) + } + + const type = file === null ? 'null' : typeof file + const constructorName = + file && + typeof file === 'object' && + 'constructor' in file && + (file as { constructor?: { name?: string } }).constructor?.name + ? ` (${(file as { constructor: { name: string } }).constructor.name})` + : '' + throw new Error(`Unsupported file input type: ${type}${constructorName}`) +} diff --git a/src/runtime/webhooks.ts b/src/runtime/webhooks.ts new file mode 100644 index 0000000..69bb307 --- /dev/null +++ b/src/runtime/webhooks.ts @@ -0,0 +1,130 @@ +import type { ApiEvent, ApiEventPayload, ApiEventType } from '../types' +import { deserializeResponseDates, type WrapperClient } from '../wrapper' +import { componentDatePlans } from '../generated/dates' + +function hasBuffer(): boolean { + return typeof Buffer !== 'undefined' +} + +function hasWebCryptoSubtle(): boolean { + return ( + typeof globalThis.crypto !== 'undefined' && + typeof globalThis.crypto.subtle !== 'undefined' + ) +} + +function signatureHexToBytes(signature: string): Uint8Array | null { + if (signature.length % 2 !== 0) return null + if (!/^[0-9a-fA-F]+$/.test(signature)) return null + const bytes = new Uint8Array(signature.length / 2) + for (let i = 0; i < signature.length; i += 2) { + bytes[i / 2] = parseInt(signature.slice(i, i + 2), 16) + } + return bytes +} + +function toArrayBuffer(bytes: Uint8Array): ArrayBuffer { + return bytes.buffer.slice( + bytes.byteOffset, + bytes.byteOffset + bytes.byteLength, + ) as ArrayBuffer +} + +function parseEvent(payload: string): ApiEvent { + let event: unknown + try { + event = JSON.parse(payload) + } catch { + throw new Error('Invalid webhook event JSON') + } + return deserializeResponseDates( + event, + componentDatePlans.ApiEvent, + ) as ApiEvent +} + +export async function validateSignature( + client: WrapperClient, + data: { + secret: string + signature: string + payload: string | Uint8Array | ArrayBuffer | ApiEventPayload + }, +): Promise> { + // Validated locally + const { secret, signature, payload } = data + let payloadString: string + if (typeof payload === 'string') { + payloadString = payload + } else if (payload instanceof Uint8Array) { + payloadString = new TextDecoder().decode(payload) + } else if (payload instanceof ArrayBuffer) { + payloadString = new TextDecoder().decode(new Uint8Array(payload)) + } else if (typeof payload === 'object') { + payloadString = JSON.stringify(payload) + } else { + throw new Error('Invalid payload type') + } + + if (hasBuffer()) { + let nodeCrypto: typeof import('crypto') | null = null + try { + nodeCrypto = await import('crypto') + } catch (e) { + // continue to other available validators + } + + if (nodeCrypto) { + const hmac = nodeCrypto.createHmac('sha256', secret) + const digestBuffer = hmac.update(payloadString).digest() + // Compare the digest with the signature and prevent timing attacks + // by using a constant-time comparison + const signatureBuffer = Buffer.from(signature, 'hex') + if (digestBuffer.length !== signatureBuffer.length) { + throw new Error('Invalid signature') + } + const isValid = nodeCrypto.timingSafeEqual(digestBuffer, signatureBuffer) + if (!isValid) { + throw new Error('Invalid signature') + } + return parseEvent(payloadString) + } + } + + if (hasWebCryptoSubtle()) { + const encoder = new TextEncoder() + const encodedData = encoder.encode(payloadString) + const encodedSecret = encoder.encode(secret) + const signatureBytes = signatureHexToBytes(signature) + if (!signatureBytes) { + throw new Error('Invalid signature') + } + const key = await globalThis.crypto.subtle.importKey( + 'raw', + encodedSecret, + { name: 'HMAC', hash: 'SHA-256' }, + false, + ['verify'], + ) + const isValid = await globalThis.crypto.subtle.verify( + 'HMAC', + key, + toArrayBuffer(signatureBytes), + encodedData, + ) + if (!isValid) { + throw new Error('Invalid signature') + } + return parseEvent(payloadString) + } + + // Fallback for runtimes without local crypto support (e.g. some RN setups) + await client.post('/webhooks/validate-signature', { + body: { + secret, + signature, + payload: payloadString, + }, + }) + return parseEvent(payloadString) +} diff --git a/src/tools/cartaPorteCatalogs.ts b/src/tools/cartaPorteCatalogs.ts index 1e06773..7c42cf0 100644 --- a/src/tools/cartaPorteCatalogs.ts +++ b/src/tools/cartaPorteCatalogs.ts @@ -1,119 +1,220 @@ -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' export default class CartaPorteCatalogs { - client: WrapperClient; - - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Air transport codes (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar códigos de transporte aéreo + * + * Devuelve entradas del catálogo de aerolíneas que coinciden con la consulta. Usado para el complemento Carta Porte. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key`, `airline_name` o `icao_designator`. + * @returns Búsqueda exitosa */ - searchAirTransportCodes(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/air-transport-codes', { - params, - }); + searchAirTransportCodes( + params: OperationQuery<'searchCartaPorteAirTransportCodes'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteAirTransportCodes'> + >(`/catalogs/cartaporte/3.1/air-transport-codes`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteAirTransportCodes, + params: params, + }) } /** - * Auto transport configurations (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar configuraciones de autotransporte + * + * Devuelve configuraciones de transporte (p. ej., camión/semirremolque). + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchTransportConfigs(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/transport-configs', { - params, - }); + searchTransportConfigs( + params: OperationQuery<'searchCartaPorteTransportConfigs'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteTransportConfigs'> + >(`/catalogs/cartaporte/3.1/transport-configs`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteTransportConfigs, + params: params, + }) } /** - * Rights of passage (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar derechos de paso + * + * Devuelve derechos de paso ferroviarios que coinciden con la consulta. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key`, `right_of_passage` o `concessionaire`. + * @returns Búsqueda exitosa */ - searchRightsOfPassage(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/rights-of-passage', { - params, - }); + searchRightsOfPassage( + params: OperationQuery<'searchCartaPorteRightsOfPassage'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteRightsOfPassage'> + >(`/catalogs/cartaporte/3.1/rights-of-passage`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteRightsOfPassage, + params: params, + }) } /** - * Customs documents (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar documentos aduaneros + * + * Devuelve tipos de documentos aduaneros. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchCustomsDocuments(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/customs-documents', { - params, - }); + searchCustomsDocuments( + params: OperationQuery<'searchCartaPorteCustomsDocuments'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteCustomsDocuments'> + >(`/catalogs/cartaporte/3.1/customs-documents`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteCustomsDocuments, + params: params, + }) } /** - * Packaging types (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar tipos de empaque + * + * Devuelve tipos de empaque para mercancías. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchPackagingTypes(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/packaging-types', { - params, - }); + searchPackagingTypes( + params: OperationQuery<'searchCartaPortePackagingTypes'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPortePackagingTypes'> + >(`/catalogs/cartaporte/3.1/packaging-types`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPortePackagingTypes, + params: params, + }) } /** - * Trailer types (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar tipos de remolque + * + * Devuelve tipos de remolque/semirremolque. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchTrailerTypes(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/trailer-types', { - params, - }); + searchTrailerTypes( + params: OperationQuery<'searchCartaPorteTrailerTypes'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteTrailerTypes'> + >(`/catalogs/cartaporte/3.1/trailer-types`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteTrailerTypes, + params: params, + }) } /** - * Hazardous materials (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar materiales peligrosos + * + * Devuelve entradas del catálogo de materiales peligrosos. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key`, `description` o `class_division`. + * @returns Búsqueda exitosa */ - searchHazardousMaterials(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/hazardous-materials', { - params, - }); + searchHazardousMaterials( + params: OperationQuery<'searchCartaPorteHazardousMaterials'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteHazardousMaterials'> + >(`/catalogs/cartaporte/3.1/hazardous-materials`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteHazardousMaterials, + params: params, + }) } /** - * Naval authorizations (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar autorizaciones navales + * + * Devuelve códigos de autorización naval (solo `key`). + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key`. + * @returns Búsqueda exitosa */ - searchNavalAuthorizations(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/naval-authorizations', { - params, - }); + searchNavalAuthorizations( + params: OperationQuery<'searchCartaPorteNavalAuthorizations'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteNavalAuthorizations'> + >(`/catalogs/cartaporte/3.1/naval-authorizations`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteNavalAuthorizations, + params: params, + }) } /** - * Port stations (air/sea/land) (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar estaciones/puertos + * + * Devuelve entradas de estaciones aéreas/marítimas/terrestres. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key`, `description` o `iata_designator`. + * @returns Búsqueda exitosa */ - searchPortStations(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/port-stations', { - params, - }); + searchPortStations( + params: OperationQuery<'searchCartaPortePortStations'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPortePortStations'> + >(`/catalogs/cartaporte/3.1/port-stations`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPortePortStations, + params: params, + }) } /** - * Marine containers (Carta Porte 3.1) - * @param {Object} params - Search parameters - * @returns {Promise} + * Buscar contenedores marítimos + * + * Devuelve tipos de contenedores marítimos. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchMarineContainers(params: Record | null) { - return this.client.get('/catalogs/cartaporte/3.1/marine-containers', { - params, - }); + searchMarineContainers( + params: OperationQuery<'searchCartaPorteMarineContainers'> | null, + ): Promise> { + return this.client.request< + OperationResponse<'searchCartaPorteMarineContainers'> + >(`/catalogs/cartaporte/3.1/marine-containers`, { + method: 'GET', + datePlan: operationDatePlans.searchCartaPorteMarineContainers, + params: params, + }) } } diff --git a/src/tools/catalogs.ts b/src/tools/catalogs.ts index ca50dd3..72434a7 100644 --- a/src/tools/catalogs.ts +++ b/src/tools/catalogs.ts @@ -1,27 +1,52 @@ -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' export default class Catalogs { - client: WrapperClient; - - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Creates a new product in your organization - * @param {Object} params - Search parameters - * @returns {Promise} + * Clave Producto/Servicio + * + * Busca en el catálogo Productos/Servicios del SAT, el cual contiene la clave a incluir en la factura. + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - searchProducts(params: Record | null) { - return this.client.get('/catalogs/products', { params }); + searchProducts( + params: OperationQuery<'searchProducts'> | null, + ): Promise> { + return this.client.request>( + `/catalogs/products`, + { + method: 'GET', + datePlan: operationDatePlans.searchProducts, + params: params, + }, + ) } /** - * Gets a paginated list of products that belong to your organization - * @param {[Object]} params - Search parameters - * @returns {Promise} + * Unidades de medida + * + * Busca en el catálogo de Unidades de Medida del SAT. + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - searchUnits(params: Record | null) { - return this.client.get('/catalogs/units', { params }); + searchUnits( + params: OperationQuery<'searchUnits'> | null, + ): Promise> { + return this.client.request>( + `/catalogs/units`, + { + method: 'GET', + datePlan: operationDatePlans.searchUnits, + params: params, + }, + ) } } diff --git a/src/tools/comercioExteriorCatalogs.ts b/src/tools/comercioExteriorCatalogs.ts index 83044d3..b138507 100644 --- a/src/tools/comercioExteriorCatalogs.ts +++ b/src/tools/comercioExteriorCatalogs.ts @@ -1,20 +1,31 @@ -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' export default class ComercioExteriorCatalogs { - client: WrapperClient; - - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Search tariff fractions for Comercio Exterior - * @param {Object} params - Search parameters (q, page, limit) - * @returns {Promise} + * Buscar fracciones arancelarias + * + * Devuelve fracciones arancelarias que coinciden con la consulta. + * + * @param params - Parámetros de consulta. + * @param params.q - Prefijo para buscar en `key` o `description`. + * @returns Búsqueda exitosa */ - searchTariffFractions(params: { q: string; page?: number; limit?: number }) { - return this.client.get('/catalogs/comercioexterior/2.0/tariff-fractions', { - params, - }); + searchTariffFractions( + params: OperationQuery<'searchComercioExteriorTariffFractions'>, + ): Promise> { + return this.client.request< + OperationResponse<'searchComercioExteriorTariffFractions'> + >(`/catalogs/comercioexterior/2.0/tariff-fractions`, { + method: 'GET', + datePlan: operationDatePlans.searchComercioExteriorTariffFractions, + params: params, + }) } } diff --git a/src/tools/tools.ts b/src/tools/tools.ts index d24f2c1..f1ea213 100644 --- a/src/tools/tools.ts +++ b/src/tools/tools.ts @@ -1,24 +1,57 @@ -import { WrapperClient } from '../wrapper'; - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' export default class Tools { - client: WrapperClient; + constructor(public client: WrapperClient) {} /** - * @param {Client} client + * Validar RFC + * + * Consulta el estado de un RFC en la lista de **EFOS** (Empresas que + * Facturan Operaciones Simuladas). Al aparecer en esta lista, el RFC es o + * fue sospechoso de incurrir en simulación de operaciones fiscales + * (empresas factureras). + * + * La respuesta (detallada más abajo) incluye los resultados de esta + * validación. Se incluye la propiedad + * booleana `is_valid`, que Facturapi resuelve interpretando la respuesta. + * Un valor de `true` para esta propiedad indica que el RFC no tiene asuntos + * por resolver y está libre de problemas; y lo contrario para `false`. + * + * Adicionalmente puedes consultar la propiedad data para ver los valores + * en bruto de la consulta al SAT. + * + * @param taxId - taxId + * @returns Resultado de la validación */ - constructor(client: WrapperClient) { - this.client = client; + validateTaxId( + taxId: OperationQuery<'validateTaxId'>['tax_id'], + ): Promise> { + return this.client.request>( + `/tools/tax_id_validation`, + { + method: 'GET', + datePlan: operationDatePlans.validateTaxId, + params: { tax_id: taxId }, + }, + ) } /** - * Validates a tax_id in EFOS list - * @param {Object} taxId - Search parameters - * @returns {Promise} + * Health check (Pulso) + * + * Comprueba que la API está disponible. Este endpoint requiere una llave secreta de API. + * + * @returns La API está operando con normalidad. */ - validateTaxId(taxId: string) { - return this.client.get('/tools/tax_id_validation', { - params: { - tax_id: taxId, - }, - }); + checkApiHealth(): Promise> { + return this.client.request>(`/check`, { + method: 'GET', + datePlan: operationDatePlans.checkApiHealth, + }) } } diff --git a/src/tools/webhooks.ts b/src/tools/webhooks.ts index 66731e1..f60251d 100644 --- a/src/tools/webhooks.ts +++ b/src/tools/webhooks.ts @@ -1,192 +1,126 @@ -import { - SearchResult, - Webhook, - ApiEvent, - ApiEventType, -} from '../types'; -import { WrapperClient } from '../wrapper'; - -function hasBuffer(): boolean { - return typeof Buffer !== 'undefined'; -} - -function hasWebCryptoSubtle(): boolean { - return ( - typeof globalThis.crypto !== 'undefined' && - typeof globalThis.crypto.subtle !== 'undefined' - ); -} - -function signatureHexToBytes(signature: string): Uint8Array | null { - if (signature.length % 2 !== 0) return null; - if (!/^[0-9a-fA-F]+$/.test(signature)) return null; - const bytes = new Uint8Array(signature.length / 2); - for (let i = 0; i < signature.length; i += 2) { - bytes[i / 2] = parseInt(signature.slice(i, i + 2), 16); - } - return bytes; -} - -function toArrayBuffer(bytes: Uint8Array): ArrayBuffer { - return bytes.buffer.slice( - bytes.byteOffset, - bytes.byteOffset + bytes.byteLength, - ) as ArrayBuffer; -} - +// Generated by pnpm generate:sdk. Do not edit directly. +import type { WrapperClient } from '../wrapper' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +import { operationDatePlans } from '../generated/dates' +import type { ApiEvent, ApiEventPayload, ApiEventType } from '../types' +import { validateSignature } from '../runtime/webhooks' export default class Webhooks { - client: WrapperClient; - - constructor(client: WrapperClient) { - this.client = client; - } - + constructor(public client: WrapperClient) {} /** - * Creates a new webhook in your organization - * @param data - Webhook options - * @returns Webhook object + * Crear Webhook + * + * Registra un nuevo webhook en tu organización de Facturapi. + * Utiliza esta llamada para recibir notificaciones de eventos asíncronos a la API. + * Los webhooks de ambiente test y ambiente live son independientes. + * + * @param data - Datos de la solicitud. + * @returns Nuevo objeto `Webhook` creado */ - create(data: Record): Promise { - return this.client.post('/webhooks', { body: data }); + create( + data: OperationBody<'createWebhook'>, + ): Promise> { + return this.client.request>( + `/webhooks`, + { + method: 'POST', + datePlan: operationDatePlans.createWebhook, + body: data, + }, + ) } /** - * Gets a paginated list of webhooks that belong to your organization - * @param params - Search parameters - * @returns Search results object. The object contains a `data` property with the list of webhooks. + * Listar webhooks + * + * Retorna una lista de webhooks creados previamente para la organización. + * + * @param params - Parámetros de consulta. + * @returns Resultado de la búsqueda */ - list(params: Record): Promise> { - if (!params) { - params = {}; - } - return this.client.get('/webhooks', { params }); + list( + params: OperationQuery<'listWebhooks'>, + ): Promise> { + return this.client.request>(`/webhooks`, { + method: 'GET', + datePlan: operationDatePlans.listWebhooks, + params: params, + }) } /** - * Gets a single webhook object - * @param id - Webhook Id - * @returns Webhook object + * Obtener webhook por ID + * + * Regresa el objeto "Webhook" relacionado al `id` especificado. + * + * @param id - ID del objeto a obtener + * @returns Objeto `Webhook` */ - retrieve(id: string): Promise { - if (!id) return Promise.reject(new Error('id is required')); - return this.client.get('/webhooks/' + id); + retrieve(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/webhooks/${encodeURIComponent(id)}`, + { method: 'GET', datePlan: operationDatePlans.getWebhook }, + ) } /** - * Updates a webhook - * @param id - Webhook Id - * @param data Updated webhook data - * @returns + * Editar webhook + * + * Actualiza la información de un Webhook existente con los parámetros que envíes en la petición. + * + * @param id - ID del objeto a editar + * @param data - Datos de la solicitud. + * @returns Objeto `Webhook` editado correctamente */ - update(id: string, data: Record): Promise { - return this.client.put('/webhooks/' + id, { body: data }); + update( + id: string, + data: OperationBody<'editWebhook'>, + ): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/webhooks/${encodeURIComponent(id)}`, + { method: 'PUT', datePlan: operationDatePlans.editWebhook, body: data }, + ) } /** - * Permanently removes a webhook from your organization. - * @param id - Webhook Id - * @returns Deleted webhook + * Eliminar Webhook + * + * Elimina el webhook perteneciente a la organización. + * + * @param id - ID del objeto a eliminar + * @returns Objeto `Webhook` eliminado correctamente */ - del(id: string): Promise { - return this.client.delete('/webhooks/' + id); + del(id: string): Promise> { + if (!id) return Promise.reject(new Error('id is required')) + + return this.client.request>( + `/webhooks/${encodeURIComponent(id)}`, + { method: 'DELETE', datePlan: operationDatePlans.deleteWebhook }, + ) } /** - * Validate the response of webhook with the secret and facturapi-signature - * @param secret - Webhook Secret, received in the webhook creation - * @param signature - Facturapi Signature Header - * @param payload - Received event object to validate - * @returns When the signature is valid, it returns the event object + * Valida la firma del webhook y devuelve el evento con sus fechas como Date. + * Usa criptografía local cuando está disponible; en otros entornos consulta la API. + * @param data - Datos para verificar el evento. + * @param data.secret - Secreto del webhook. + * @param data.signature - Firma recibida en el encabezado Facturapi-Signature. + * @param data.payload - Preferentemente, el cuerpo original como texto o bytes. También acepta un evento como objeto. + * @returns Evento validado, siempre como objeto. + * @throws Si la firma es inválida o el payload no se puede interpretar como JSON. */ - async validateSignature(data: { - secret: string; - signature: string; - payload: string | Uint8Array | ArrayBuffer | ApiEvent; + validateSignature(data: { + secret: string + signature: string + payload: string | Uint8Array | ArrayBuffer | ApiEventPayload }): Promise> { - // Validated locally - const { secret, signature, payload } = data; - let payloadString: string; - if (typeof payload === 'string') { - payloadString = payload; - } else if (payload instanceof Uint8Array) { - payloadString = new TextDecoder().decode(payload); - } else if (payload instanceof ArrayBuffer) { - payloadString = new TextDecoder().decode(new Uint8Array(payload)); - } else if ( - typeof Buffer !== 'undefined' && - Buffer.isBuffer(payload) - ) { - payloadString = payload.toString('utf8'); - } else if (typeof payload === 'object') { - payloadString = JSON.stringify(payload); - } else { - throw new Error('Invalid payload type'); - } - - if (hasBuffer()) { - let nodeCrypto: typeof import('crypto') | null = null; - try { - nodeCrypto = await import('crypto'); - } catch (e) { - // continue to other available validators - } - - if (nodeCrypto) { - const hmac = nodeCrypto.createHmac('sha256', secret); - const digestBuffer = hmac - .update(payloadString) - .digest(); - // Compare the digest with the signature and prevent timing attacks - // by using a constant-time comparison - const signatureBuffer = Buffer.from(signature, 'hex'); - if (digestBuffer.length !== signatureBuffer.length) { - throw new Error('Invalid signature'); - } - const isValid = nodeCrypto.timingSafeEqual( - digestBuffer, - signatureBuffer, - ); - if (!isValid) { - throw new Error('Invalid signature'); - } - return JSON.parse(payloadString) as ApiEvent; - } - } - - if (hasWebCryptoSubtle()) { - const encoder = new TextEncoder(); - const encodedData = encoder.encode(payloadString); - const encodedSecret = encoder.encode(secret); - const signatureBytes = signatureHexToBytes(signature); - if (!signatureBytes) { - throw new Error('Invalid signature'); - } - const key = await globalThis.crypto.subtle.importKey( - 'raw', - encodedSecret, - { name: 'HMAC', hash: 'SHA-256' }, - false, - ['verify'], - ); - const isValid = await globalThis.crypto.subtle.verify( - 'HMAC', - key, - toArrayBuffer(signatureBytes), - encodedData, - ); - if (!isValid) { - throw new Error('Invalid signature'); - } - return JSON.parse(payloadString) as ApiEvent; - } - - // Fallback for runtimes without local crypto support (e.g. some RN setups) - return this.client.post('/webhooks/validate-signature', { - body: { - secret, - signature, - payload: payloadString, - }, - }); + return validateSignature(this.client, data) } } diff --git a/src/types/common.ts b/src/types/common.ts index c1d01a8..e225825 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -1,158 +1,31 @@ -import { TaxType, TaxFactor, IepsMode, TaxSystem } from '../enums'; - -export interface Address { - street?: string | null; - exterior?: string | null; - interior?: string | null; - neighborhood?: string | null; - zip: string; - city?: string | null; - municipality?: string | null; - state?: string | null; - country: string; -} - -export interface SearchResult { - /** Page number. Absent in cursor searches and when the search has no matches. */ - page?: number; - /** Total pages derived from the (possibly capped) total. Absent in cursor searches. */ - total_pages?: number; - /** - * Total matching results. Capped (approximate) when `totals_are_capped` is - * true, and only reported on the first request of a cursor sequence. - */ - total_results?: number; - /** True when total_results is capped at the maximum search count. */ - totals_are_capped?: boolean; - /** Cursor to the previous slice (cursor searches only). */ - previous_cursor?: string | null; - /** Cursor to the next slice (cursor searches only). */ - next_cursor?: string | null; - data: T[]; -} - -/** Params that select page pagination (the default). */ +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type Address = Output['CommonAddressProperties'] +export type InvoiceItemPart = Output['Parts'] +export type InvoiceItemThirdParty = Output['ThirdParty'] +export type Tax = Output['BaseTax'] | Output['IepsTax'] +export type LocalTax = Output['LocalTax'] +export type ProductInfo = Output['LineItemProduct'] +export type CustomerInfo = Output['CustomerInfo'] +export type InvoiceItem = Output['LineItem'] +export type XmlNamespace = Output['NamespaceProperties'] +export type RelatedDocument = Output['RelatedDocument'] +export type GenericResponse = Output['OkResponse'] +export type SendEmailBody = OperationBody<'sendInvoiceByEmail'> +export type SignedDownloadUrl = Output['SignedDownloadUrl'] +export * from './runtime' +export type SearchResult = Output['SearchResult'] & { data: T[] } export type PageSearchParams = ({ pagination?: 'page' } | { page: number }) & - Record; - -/** Params that select cursor pagination (page mode is the default). */ -export type CursorSearchParams = ({ pagination: 'cursor' } | { after: string } | { before: string }) & - Record; - -export interface InvoiceItemPart { - quantity: number; - product_key: string; - description: string; - unit_name: string; - sku: string; - unit_price: number; -} - -export interface InvoiceItemThirdParty { - tax_id: string; - legal_name: string; - tax_system: string; - zip: string; -} - -export interface Tax { - base?: number; - amount: number; - rate: number; - type: TaxType; - withholding: boolean; - factor: TaxFactor; - ieps_mode?: IepsMode; -} - -export interface LocalTax { - rate: number; - type: string; - withholding: boolean; - base?: number; - factor?: TaxFactor; -} - -export interface ProductInfo { - id?: string; - description: string; - product_key: string; - unit_key: string; - unit_name: string; - price: number; - taxability: string; - tax_included: boolean; - taxes: Tax[]; - local_taxes: LocalTax[]; - sku: string; -} - -export interface CustomerInfo { - id?: string; - legal_name: string; - tax_id: string; - tax_system: TaxSystem; - address: { - zip: string; - country: string; - }; -} - -export interface InvoiceItem { - quantity: number; - product: ProductInfo; - discount: number; - customs_keys: [string]; - third_party: InvoiceItemThirdParty; - complement: string; - parts: InvoiceItemPart[]; - property_tax_account: string[]; -} - -export interface XmlNamespace { - prefix: string; - uri: string; - schema_location: string; -} - -export interface RelatedDocument { - relationship: string; - uuid: string; -} - -export interface GenericResponse { - ok: boolean; -} - -export interface SendEmailBody { - email?: string | string[]; -} - -export interface NodeLikeReadableStream { - pipe?(destination: T, options?: { end?: boolean }): T; - on(event: 'data', listener: (chunk: unknown) => void): unknown; - on(event: 'end', listener: () => void): unknown; - on(event: 'error', listener: (error: unknown) => void): unknown; -} - -export type BinaryDownload = Blob | NodeLikeReadableStream; -export type BinaryInput = - | Blob - | File - | ArrayBuffer - | Uint8Array - | NodeLikeReadableStream; - -/** - * A short-lived URL that downloads one representation of a document. - * - * The URL is a bearer credential for that file: whoever holds it can download - * it until `expires_at`. It belongs in the hands of the caller's own user, not - * in storage or logs. - */ -export interface SignedDownloadUrl { - url: string; - expires_at: string; - content_type: string; - filename: string; -} + Record +export type CursorSearchParams = ( + { pagination: 'cursor' } | { after: string } | { before: string } +) & + Record diff --git a/src/types/complements.ts b/src/types/complements.ts index 0a27c15..b2aaeab 100644 --- a/src/types/complements.ts +++ b/src/types/complements.ts @@ -1,78 +1,19 @@ -export interface PaymentRelatedDocumentTax { - base: number; - rate: number; - type: string; - factor: string; - withholding: boolean; -} - -export interface PaymentRelatedDocument { - uuid: string; - amount: number; - installment: number; - last_balance: number; - currency: string; - exchange: number; - folio_number: string; - series: string; - taxability?: string; - taxes: PaymentRelatedDocumentTax[]; -} - -export interface PagoComplementData { - payment_form: string; - date: Date; - related_documents: PaymentRelatedDocument[]; - currency: string; - exchange: number; - numOperacion: string; - rfcEmisorCtaOrd: string; - nomBancoOrdExt: string; - ctaOrdenante: string; - rfcEmisorCtaBen: string; - ctaBeneficiario: string; - tipoCadPago: string; - certPago: string; - cadPago: string; - selloPago: string; -} - -export interface NominaReceptor { - curp?: string; - num_seguridad_social?: string; - fecha_inicio_rel_laboral?: Date | string; - antiguedad: boolean | string; - tipo_contrato: string; - sindicalizado?: boolean; - tipo_jornada?: string; - tipo_regimen: string; - num_empleado: string; - departamento?: string; - puesto?: string; - riesgo_puesto?: string; - periodicidad_pago: string; - banco?: string; - nombre_banco?: string; - cuenta_bancaria?: string; - salario_base_cot_apor?: number; - salario_diario_integrado?: number; - clave_ent_fed: string; - sub_contratacion?: { - rfc_labora: string; - porcentaje_tiempo: number; - }[]; -} - -export interface NominaComplementData { - fecha_inicial_pago: string | Date; - fecha_final_pago: string | Date; - percepciones: any; - deducciones: any; - otros_pagos: any; - incapacidades: any; - emisor: any; - receptor: NominaReceptor; - tipo_nomina: string; - fecha_pago: string | Date; - num_dias_pagados: number; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type PagoComplementData = Output['PaymentProperties'] +export type PaymentRelatedDocument = NonNullable< + PagoComplementData['related_documents'] +>[number] +export type PaymentRelatedDocumentTax = NonNullable< + PaymentRelatedDocument['taxes'] +>[number] +export type NominaReceptor = Output['NominaReceptorProperties'] +export type NominaComplementData = Output['NominaComplementDataProperties'] diff --git a/src/types/customer.ts b/src/types/customer.ts index e4aeb67..d1519c8 100644 --- a/src/types/customer.ts +++ b/src/types/customer.ts @@ -1,31 +1,13 @@ -import { InvoiceUse } from '../enums'; -import { Address } from './common'; - -export interface TaxInfoValidationError { - path: string; - message: string; -} - -export interface TaxInfoValidation { - is_valid: boolean; - errors: TaxInfoValidationError[]; -} - -export interface Customer { - id: string; - livemode: boolean; - organization: string; - created_at: Date; - tax_id: string; - tax_system?: string; - legal_name: string; - email: string; - phone?: string; - curp?: string; - address: Address; - external_id?: string; - default_invoice_use?: InvoiceUse; - sat_validated_at?: Date; - edit_link?: string; - edit_link_expires_at?: Date; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type TaxInfoValidation = OperationResponse<'validateCustomerTaxInfo'> +export type TaxInfoValidationError = TaxInfoValidation['errors'][number] +export type Customer = Output['Customer'] diff --git a/src/types/index.ts b/src/types/index.ts index 075e619..b42060c 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,9 +1,10 @@ -export * from './common'; -export * from './complements'; -export * from './customer'; -export * from './product'; -export * from './retention'; -export * from './organization'; -export * from './receipt'; -export * from './invoice'; -export * from './webhook'; +export * from './common' +export * from './complements' +export * from './customer' +export * from './product' +export * from './retention' +export * from './organization' +export * from './receipt' +export * from './invoice' +export * from './webhook' +export * from '../generated/models' diff --git a/src/types/invoice.ts b/src/types/invoice.ts index 46a9e63..13ae2c5 100644 --- a/src/types/invoice.ts +++ b/src/types/invoice.ts @@ -1,161 +1,22 @@ -import { - CancellationMotive, - CancellationStatus, - InvoiceComplementType, - InvoiceStatus, - InvoiceType, - InvoiceUse, - InvoicingPeriod, - IssuingType, - PaymentForm, - PaymentMethod, -} from '../enums'; -import { - Address, - CustomerInfo, - InvoiceItem, - RelatedDocument, - XmlNamespace, -} from './common'; -import { NominaComplementData, PagoComplementData } from './complements'; - -export interface GlobalInfo { - periodicity: InvoicingPeriod; - months: string; - year: number; -} - -export interface InvoiceComplement { - type: InvoiceComplementType; - data: string | PagoComplementData[] | NominaComplementData; -} - -export interface Invoice { - id: string; - organization: string; - livemode: boolean; - created_at: Date; - date: Date; - issuer_type: IssuingType; - type: InvoiceType; - status: InvoiceStatus; - cfdi_version: number; - issuer_info: CustomerInfo; - payment_form: PaymentForm; - payment_method: PaymentMethod; - currency: string; - exchange: number; - uuid: string; - customer: CustomerInfo; - total: number; - use: InvoiceUse; - folio_number: number | string; - series: string; - is_ready_to_stamp: boolean; - items: InvoiceItem[]; - address: Address; - amount_due?: number | null; - verification_url?: string | null; - verification_carta_porte?: string | null; - cancellation_status: CancellationStatus; - external_id?: string | null; - idempotency_key?: string | null; - stamp?: { - date: string; - sat_signature: string; - sat_cert_number: string; - signature: string; - complement_string: string; - rfc_provider_cert: string; - } | null; - addenda?: string | null; - conditions: string | null; - - pdf_custom_section: string | null; - export?: string | null; - global?: GlobalInfo | null; - cancellation?: { - requested_at: Date; - status: CancellationStatus; - last_checked: Date; - motive: string; - substitutionUUID: string; - } | null; - complements?: InvoiceComplement[] | null; - related_documents?: RelatedDocument[] | null; - namespaces?: XmlNamespace[] | null; - received_payment_ids?: string[] | null; - target_invoice_ids?: string[] | null; -} - -export interface CancelInvoiceOptions { - motive: CancellationMotive; - substitution?: string; -} - -export interface CreateZipRequestData { - year: number; - month: number; - issuer_type: IssuingType; - invoice_types?: InvoiceType[]; -} - -export interface ListZipRequestsParams { - year?: number; - month?: number; - status?: string; - limit?: number; - page?: number; -} - -export interface ZipRequest { - id: string; - year: number; - month: number; - issuer_type: IssuingType; - invoice_types: InvoiceType[]; - status: string; - created_at?: Date; - updated_at?: Date; - [key: string]: unknown; -} - -export interface PaymentSummaryParams { - /** - * Amount being paid on the invoice, expressed in the invoice currency. - * Cannot exceed the outstanding balance. - */ - amount: number; -} - -export interface PaymentSummaryTax { - /** Tax base prorated to the paid amount */ - base: number; - /** Tax rate or quota */ - rate: number; - /** Tax type (VAT, income tax, etc.) */ - type: string; - /** Factor type (Rate, Exempt, etc.) */ - factor: string; - /** Whether this tax is a withholding */ - withholding: boolean; -} - -export interface PaymentSummary { - /** Invoice UUID */ - uuid: string; - folio_number?: number | null; - series?: string | null; - /** Installment number corresponding to this payment */ - installment: number; - /** Invoice outstanding balance before this payment */ - last_balance: number; - /** Invoice total */ - total: number; - /** Invoice currency */ - currency: string; - /** Amount paid in this installment */ - amount: number; - /** Invoice taxes prorated to the paid amount */ - taxes: PaymentSummaryTax[]; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type GlobalInfo = NonNullable +export type InvoiceComplement = NonNullable< + Output['InvoiceProperties']['complements'] +>[number] +export type Invoice = Output['Invoice'] +export type CancelInvoiceOptions = Input['CancellationQueryInput'] +export type CreateZipRequestData = OperationBody<'createInvoiceZipRequest'> +export type ListZipRequestsParams = OperationQuery<'listInvoiceZipRequests'> +export type ZipRequest = Output['InvoiceZipRequest'] +export type PaymentSummaryParams = OperationQuery<'getInvoicePaymentSummary'> +export type PaymentSummary = OperationResponse<'getInvoicePaymentSummary'> +export type PaymentSummaryTax = NonNullable[number] diff --git a/src/types/organization.ts b/src/types/organization.ts index fd90841..fcbd9ef 100644 --- a/src/types/organization.ts +++ b/src/types/organization.ts @@ -1,169 +1,28 @@ -import { GlobalInvoicePeriodicity, TaxSystem } from '../enums'; -import { Address } from './common'; - -export interface Series { - series: string; - next_folio: number; - next_folio_test: number; -} - -export interface OrganizationDefaultSeriesUpdateInput { - type: 'I' | 'E' | 'P' | 'N' | 'T'; - series: string; -} - -export interface ApiKeys { - id: string; - first_12: string; - created_at: string; -} - -export interface OrganizationUserAccess { - id: string; - full_name: string; - email: string; - role: string | null; - role_name: string | null; - organization: string; - operations: string[]; - created_at: string; - updated_at: string; -} - -export interface OrganizationInvite { - id: string; - created_at: string; - email: string; - organization_name: string; - role: string | null; - role_name: string | null; - roles: string[]; - expires_at: string | null; -} - -export interface OrganizationInviteCreateInput { - email: string; - role?: string; -} - -export interface OrganizationInviteResponseInput { - accept: boolean; -} - -export interface OrganizationTeamRole { - id: string; - name: string; - template_code: string | null; - scope: string; - organization: string | null; - operations: string[]; - used_by: number; - created_at: string; - updated_at: string; - created_by?: Record | null; - updated_by?: Record | null; -} - -export interface OrganizationTeamRoleCreateInput { - name: string; - template_code?: string | null; - add?: string[]; - remove?: string[]; -} - -export interface OrganizationTeamRoleUpdateInput { - name?: string; - template_code?: string | null; - add?: string[]; - remove?: string[]; -} - -export interface OrganizationTeamRoleTemplate { - code: string; - name: string; - description: string; - operations: string[]; -} - -export interface Organization { - id: string; - created_at: Date; - /** - * @deprecated Organization-level plans are no longer offered. Use the add_ons property to determine contracted features. - */ - plan: string | null; - add_ons: string[]; - is_production_ready: boolean; - pending_steps: { - type: string; - description: string; - }[]; - logo_url?: string | null; - domain?: string | null; - custom_domain?: string | null; - timezone: string; - legal: { - name: string; - legal_name: string; - tax_id: string; - tax_system: TaxSystem; - address: Address; - phone: string; - website: string; - support_email: string; - curp: string; - }; - customization: { - color: string; - // TODO: Delete? - // next_folio_number: number; - // next_folio_number_test: number; - // default_series: this.default_series, - pdf_extra: { - codes: boolean; - address_codes: boolean; - product_key: boolean; - round_unit_price: boolean; - tax_breakdown: boolean; - ieps_breakdown: boolean; - render_carta_porte: boolean; - repeat_signature: boolean; - }; - default_series: { - I: string; - E: string; - P: string; - N: string; - T: string; - }; - has_logo: string; - }; - certificate: { - has_certificate: boolean; - updated_at?: Date | null; - expires_at?: Date | null; - serial_number?: string | null; - }; - fiel: { - has_certificate: boolean; - updated_at?: Date | null; - expires_at?: Date | null; - serial_number?: string | null; - }; - receipts: { - periodicity: GlobalInvoicePeriodicity; - duration_days: number; - next_folio_number: number; - next_folio_number_test: number; - }; - self_invoice: { - allowed_cfdi_uses: string[]; - apply_resico_isr: boolean; - support_email: string; - support_email_verified: boolean; - }; - pending_plan_update: { - plan: string; - scheduled_for: Date; - }; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type Series = Output['OrganizationSeriesGroup'] +export type OrganizationDefaultSeriesUpdateInput = + Input['OrganizationSeriesDefaultInput'] +export type ApiKeys = OperationResponse<'listLiveApiKeys'>[number] +export type OrganizationUserAccess = Output['OrganizationUserAccess'] +export type OrganizationInvite = Output['OrganizationInvite'] +export type OrganizationInviteCreateInput = + Input['OrganizationInviteCreateInput'] +export type OrganizationInviteResponseInput = + Input['OrganizationInviteRespondInput'] +export type OrganizationTeamRole = Output['OrganizationPermissionRole'] +export type OrganizationTeamRoleCreateInput = + Input['OrganizationPermissionRoleCreateInput'] +export type OrganizationTeamRoleUpdateInput = + Input['OrganizationPermissionRoleUpdateInput'] +export type OrganizationTeamRoleTemplate = + Output['OrganizationPermissionRoleTemplate'] +export type Organization = Output['Organization'] diff --git a/src/types/product.ts b/src/types/product.ts index 9351676..e8d61f9 100644 --- a/src/types/product.ts +++ b/src/types/product.ts @@ -1,17 +1,11 @@ -import type { LocalTax, Tax } from './common'; - -export interface Product { - id: string; - organization: string; - livemode: boolean; - product_key: string; - description: string; - price: number; - created_at: Date; - tax_included: boolean; - taxability: string; - taxes: Tax[]; - local_taxes: LocalTax[]; - unit_key: string; - unit_name: string; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type Product = Output['Product'] diff --git a/src/types/receipt.ts b/src/types/receipt.ts index 1b6891c..d60a099 100644 --- a/src/types/receipt.ts +++ b/src/types/receipt.ts @@ -1,40 +1,13 @@ -import type { ReceiptStatus } from '../enums' -import type { InvoiceItem } from './common' -import type { Invoice } from './invoice' - -export interface Receipt { - id: string - created_at: Date - date: Date - api_version: number - livemode: boolean - organization: string - folio_number?: number - external_id?: string - idempotency_key?: string - branch: string - payment_form: string - items: InvoiceItem[] - currency: string - exchange: number - total: number - invoice: string - expires_at: Date - key: string - status: ReceiptStatus - self_invoice_url: string -} - -export interface ReceiptsToInvoiceInput { - keys: string[] - customer?: string | Record - use?: string - dry_run?: boolean - payment_form?: string | null -} - -export interface PreviewReceiptsToInvoicePdfInput { - keys: string[] - customer?: string | Record | null - use?: string -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type Receipt = Output['Receipt'] +export type ReceiptsToInvoiceInput = Input['ToInvoiceInput'] +export type PreviewReceiptsToInvoicePdfInput = Input['ToInvoicePreviewInput'] diff --git a/src/types/retention.ts b/src/types/retention.ts index 4d94233..f5dc7f1 100644 --- a/src/types/retention.ts +++ b/src/types/retention.ts @@ -1,47 +1,11 @@ -import { InvoiceStatus } from '../enums'; -import { CustomerInfo, RelatedDocument, XmlNamespace } from './common'; - -export interface Retention { - created_at: Date; - customer: CustomerInfo; - organization: string; - livemode: boolean; - status: InvoiceStatus; - uuid: string; - external_id?: string; - fecha_exp: Date; - cve_retenc: string; - folio_int?: string; - desc_retenc?: string; - periodo: { - mes_ini: number; - mes_fin: number; - ejerc: number; - }; - totales: { - monto_tot_grav: number; - monto_tot_exent: number; - monto_tot_operacion: number; - monto_tot_ret: number; - imp_retenidos: Array<{ - base_ret?: number; - impuesto?: string; - tipo_pago_ret: string; - monto_ret: number; - pago_provisional: boolean; - }>; - }; - namespaces?: XmlNamespace[]; - related_documents?: RelatedDocument[]; - complements?: string[]; - addenda?: string[]; - cancellation_receipt?: string; - stamp?: { - date: string; - sat_signature: string; - sat_cert_number: string; - signature: string; - }; - pdf_custom_section?: string; - verification_url: string; -} +// Generated by pnpm generate:sdk. Do not edit directly. +import type { components as InputComponents } from '../generated/input' +import type { components as OutputComponents } from '../generated/output' +import type { + OperationBody, + OperationQuery, + OperationResponse, +} from '../generated/contracts' +type Input = InputComponents['schemas'] +type Output = OutputComponents['schemas'] +export type Retention = Output['Retention'] diff --git a/src/types/runtime.ts b/src/types/runtime.ts new file mode 100644 index 0000000..b62c020 --- /dev/null +++ b/src/types/runtime.ts @@ -0,0 +1,10 @@ +export interface NodeLikeReadableStream { + pipe?(destination: T, options?: { end?: boolean }): T + on(event: 'data', listener: (chunk: unknown) => void): unknown + on(event: 'end', listener: () => void): unknown + on(event: 'error', listener: (error: unknown) => void): unknown +} + +export type BinaryDownload = Blob | NodeLikeReadableStream +export type BinaryInput = + Blob | File | ArrayBuffer | Uint8Array | Pick diff --git a/src/types/webhook.ts b/src/types/webhook.ts index 22a27d5..7ddc0a3 100644 --- a/src/types/webhook.ts +++ b/src/types/webhook.ts @@ -1,6 +1,5 @@ -import { Receipt } from './receipt'; -import { Invoice } from './invoice'; -import { Customer } from './customer'; +import type { components } from '../generated/output' +import type { components as Input } from '../generated/input' export enum ApiEventType { RECEIPT_SELF_INVOICE_COMPLETE = 'receipt.self_invoice_complete', @@ -18,49 +17,21 @@ export enum ApiEventDataType { CUSTOMER = 'customer', } -type ApiEventTypeMap = { - [ApiEventType.RECEIPT_SELF_INVOICE_COMPLETE]: ApiEventDataType.RECEIPT; - [ApiEventType.INVOICE_CANCELLATION_STATUS_UPDATED]: ApiEventDataType.INVOICE; - [ApiEventType.RECEIPT_STATUS_UPDATED]: ApiEventDataType.RECEIPT; - [ApiEventType.GLOBAL_INVOICE]: ApiEventDataType.INVOICE; - [ApiEventType.INVOICES_STATUS_UPDATED]: ApiEventDataType.INVOICE; - [ApiEventType.INVOICES_CREATED_FROM_DASHBOARD]: ApiEventDataType.INVOICE; - [ApiEventType.CUSTOMER_EDIT_LINK_COMPLETED]: ApiEventDataType.CUSTOMER; - '': ''; -}; - -type ApiEventDataTypeMap = { - [ApiEventDataType.RECEIPT]: Receipt; - [ApiEventDataType.INVOICE]: Invoice; - [ApiEventDataType.CUSTOMER]: Customer; - '': any; -}; - export enum WebhookEndpointStatus { ENABLED = 'enabled', DISABLED = 'disabled', } -export interface Webhook { - created_at: Date; - organization: string; - livemode: boolean; - enabled_events: (ApiEventType | '*')[]; - description?: string; - url: string; - secret?: string; - status: WebhookEndpointStatus; -} - -export interface ApiEventData { - type: T; - object: ApiEventDataTypeMap[T]; -} - -export interface ApiEvent { - created_at: Date; - organization: string; - livemode: boolean; - type: T extends '' ? ApiEventType : T; - data: ApiEventData; -} +export type Webhook = components['schemas']['Webhook'] +export type ApiEvent = Extract< + components['schemas']['ApiEvent'], + { type: T extends '' ? `${ApiEventType}` : `${T}` } +> +export type ApiEventData = Extract< + ApiEvent['data'], + { type: T extends '' ? `${ApiEventDataType}` : `${T}` } +> +export type ApiEventPayload = Extract< + Input['schemas']['ApiEvent'], + { type: T extends '' ? `${ApiEventType}` : `${T}` } +> diff --git a/src/wrapper.ts b/src/wrapper.ts index 6dc4070..bb960f3 100644 --- a/src/wrapper.ts +++ b/src/wrapper.ts @@ -1,92 +1,90 @@ -import { - BASE_URL, - BASE_URL_V1, - DEFAULT_API_VERSION, -} from './constants'; +import { deserializeResponseDates } from './runtime/dates' +export { deserializeResponseDates } from './runtime/dates' +import { BASE_URL, BASE_URL_V1, DEFAULT_API_VERSION } from './constants' const getRuntimeFetch = () => { - const runtimeFetch = globalThis.fetch; + const runtimeFetch = globalThis.fetch if (!runtimeFetch) { throw new Error( 'Fetch API is not available in this runtime. Use Node.js 18+ or provide a global fetch implementation.', - ); + ) } - return runtimeFetch.bind(globalThis); -}; + return runtimeFetch.bind(globalThis) +} function hasBuffer(): boolean { - return typeof Buffer !== 'undefined'; + return typeof Buffer !== 'undefined' } type FormDataLike = { - append: (name: string, value: unknown, fileName?: string) => void; -}; + append: (name: string, value: unknown, fileName?: string) => void +} -export type UniversalFormData = FormData | FormDataLike; +export type UniversalFormData = FormData | FormDataLike export interface FacturapiErrorDetail { - code?: string; - message?: string; - path?: string; - location?: string; - source?: string; - [key: string]: unknown; + code?: string + message?: string + path?: string + location?: string + source?: string + [key: string]: unknown } export interface FacturapiErrorOptions { - message: string; - status: number; - code?: string; - path?: string; - location?: string; - errors?: FacturapiErrorDetail[]; - logId?: string; - headers?: Record; + message: string + status: number + code?: string + path?: string + location?: string + errors?: FacturapiErrorDetail[] + logId?: string + headers?: Record } export class FacturapiError extends Error { - status: number; - code?: string; - path?: string; - location?: string; - errors?: FacturapiErrorDetail[]; - logId?: string; - headers: Record; + status: number + code?: string + path?: string + location?: string + errors?: FacturapiErrorDetail[] + logId?: string + headers: Record constructor(options: FacturapiErrorOptions) { - super(options.message); - this.name = 'FacturapiError'; - this.status = options.status; - this.code = options.code; - this.path = options.path; - this.location = options.location; - this.errors = options.errors; - this.logId = options.logId; - this.headers = options.headers || {}; + super(options.message) + this.name = 'FacturapiError' + this.status = options.status + this.code = options.code + this.path = options.path + this.location = options.location + this.errors = options.errors + this.logId = options.logId + this.headers = options.headers || {} } } const responseHeadersToObject = (headers: Headers): Record => { - const result: Record = {}; + const result: Record = {} if (typeof headers.forEach === 'function') { headers.forEach((value, key) => { - result[key.toLowerCase()] = value; - }); - return result; + result[key.toLowerCase()] = value + }) + return result } for (const key of ['retry-after', 'x-facturapi-log-id']) { - const value = headers.get(key); + const value = headers.get(key) if (value) { - result[key] = value; + result[key] = value } } - return result; -}; + return result +} const isPlainRecord = (value: object): boolean => { - const prototype = Object.getPrototypeOf(value); - return prototype === Object.prototype || prototype === null; -}; + const prototype = Object.getPrototypeOf(value) + return prototype === Object.prototype || prototype === null +} /** * Flattens a params object into `[key, value]` pairs suitable for @@ -99,85 +97,84 @@ const isPlainRecord = (value: object): boolean => { * `RegExp`, custom instances) keep their previous string conversion. */ const buildQueryString = (params: Record): string => { - const pairs: Array<[string, string]> = []; + const pairs: Array<[string, string]> = [] const append = (value: unknown, key: string) => { if (value === undefined || value === null) { - return; + return } if (Array.isArray(value)) { if (value.length === 0) { - return; + return } for (const item of value) { - append(item, key); + append(item, key) } - return; + return } if (typeof value === 'object') { if (value instanceof Date) { - pairs.push([key, value.toISOString()]); - return; + pairs.push([key, value.toISOString()]) + return } if (isPlainRecord(value)) { - const entries = Object.entries(value); + const entries = Object.entries(value) if (entries.length === 0) { - return; + return } for (const [subKey, subValue] of entries) { - append(subValue, `${key}[${subKey}]`); + append(subValue, `${key}[${subKey}]`) } - return; + return } } - pairs.push([key, String(value)]); - }; + pairs.push([key, String(value)]) + } for (const [key, value] of Object.entries(params)) { - append(value, key); + append(value, key) } - return pairs.length ? new URLSearchParams(pairs).toString() : ''; -}; - + return pairs.length ? new URLSearchParams(pairs).toString() : '' +} const stringFrom = (value: unknown): string | undefined => - typeof value === 'string' ? value : undefined; + typeof value === 'string' ? value : undefined const statusFrom = (value: unknown, fallback: number): number => { if (typeof value === 'number') { - return value; + return value } if (typeof value === 'string') { - const parsed = Number.parseInt(value, 10); + const parsed = Number.parseInt(value, 10) if (!Number.isNaN(parsed)) { - return parsed; + return parsed } } - return fallback; -}; + return fallback +} -const responseInterceptor = async (response: Response) => { +const responseInterceptor = async (response: Response, datePlan = 0) => { if (!response.ok) { - const contentType = response.headers.get('content-type') || ''; - let bodyText: string | null = null; + const contentType = response.headers.get('content-type') || '' + let bodyText: string | null = null try { - bodyText = await response.text(); + bodyText = await response.text() } catch { - bodyText = null; + bodyText = null } - let errorData: Record | null = null; - let jsonMessage: string | null = null; + let errorData: Record | null = null + let jsonMessage: string | null = null if (contentType.includes('application/json') && bodyText) { try { - errorData = JSON.parse(bodyText) as Record; + errorData = JSON.parse(bodyText) as Record if (typeof errorData.message === 'string' && errorData.message.trim()) { - jsonMessage = errorData.message; + jsonMessage = errorData.message } } catch { // non-JSON body; fall through to body/status error } } - const headers = responseHeadersToObject(response.headers); + const headers = responseHeadersToObject(response.headers) throw new FacturapiError({ message: jsonMessage || bodyText || response.statusText, status: statusFrom(errorData?.status, response.status), @@ -189,94 +186,95 @@ const responseInterceptor = async (response: Response) => { : undefined, logId: headers['x-facturapi-log-id'], headers, - }); + }) } - const contentType = response.headers.get('content-type') || ''; - const contentDisposition = - response.headers.get('content-disposition') || ''; - const looksLikeZip = /filename=.*\.zip\b/i.test(contentDisposition); + const contentType = response.headers.get('content-type') || '' + const contentDisposition = response.headers.get('content-disposition') || '' + const looksLikeZip = /filename=.*\.zip\b/i.test(contentDisposition) const looksLikeDownload = - /attachment/i.test(contentDisposition) || looksLikeZip; + /attachment/i.test(contentDisposition) || looksLikeZip const isBinaryContentType = contentType.includes('image/') || contentType.includes('application/pdf') || contentType.includes('application/xml') || contentType.includes('application/zip') || - contentType.includes('application/octet-stream'); + contentType.includes('application/octet-stream') if (isBinaryContentType || !contentType || looksLikeDownload) { if (hasBuffer()) { - const reader = response.body?.getReader(); + const reader = response.body?.getReader() if (!reader) { - return response.blob(); + return response.blob() } try { - const { Readable } = await import('stream'); + const { Readable } = await import('stream') return new Readable({ read() { - reader.read() + reader + .read() .then(({ done, value }) => { if (done) { - this.push(null); // end stream + this.push(null) // end stream } else { - this.push(Buffer.from(value)); // push data to stream + this.push(Buffer.from(value)) // push data to stream } }) .catch((error: unknown) => { - void reader.cancel(error).catch(() => undefined); + void reader.cancel(error).catch(() => undefined) this.destroy( error instanceof Error ? error : new Error('Failed to read binary response stream'), - ); - }); + ) + }) }, - }); + }) } catch (e) { - return response.blob(); + return response.blob() } } else { - return response.blob(); + return response.blob() } } else if (contentType.includes('application/json')) { - return response.json(); + return deserializeResponseDates(await response.json(), datePlan) } - return response.text(); -}; + return response.text() +} export const createWrapper = ( apiKey: string, apiVersion: 'v1' | 'v2' = DEFAULT_API_VERSION, headers: Record = {}, ) => { - let baseURL = apiVersion === 'v1' ? BASE_URL_V1 : BASE_URL; - const defaultHeaders = new Headers(headers); - defaultHeaders.delete('Authorization'); - defaultHeaders.delete('Content-Type'); - defaultHeaders.set('Authorization', `Bearer ${apiKey}`); + let baseURL = apiVersion === 'v1' ? BASE_URL_V1 : BASE_URL + const defaultHeaders = new Headers(headers) + defaultHeaders.delete('Authorization') + defaultHeaders.delete('Content-Type') + defaultHeaders.set('Authorization', `Bearer ${apiKey}`) const client = { get baseURL(): string { - return baseURL; + return baseURL }, set baseURL(url: string) { - baseURL = url; + baseURL = url }, - async request( + async request( url: string, options?: { - params?: Record | null; - body?: any; - formData?: UniversalFormData; - method?: string; + params?: Record | null + body?: any + formData?: UniversalFormData + method?: string + datePlan?: number }, - ) { - const { params, body, formData, ...restOptions } = options || {}; - const serializedQuery = params ? buildQueryString(params) : ''; - const queryString = serializedQuery ? `?${serializedQuery}` : ''; - const requestHeaders = new Headers(defaultHeaders); + ): Promise { + const { params, body, formData, datePlan, ...restOptions } = options || {} + const serializedQuery = params ? buildQueryString(params) : '' + const queryString = serializedQuery ? `?${serializedQuery}` : '' + const requestHeaders = new Headers(defaultHeaders) if (!formData) { - requestHeaders.set('Content-Type', 'application/json'); + requestHeaders.set('Content-Type', 'application/json') } const fetchOptions: RequestInit = { ...restOptions, @@ -286,42 +284,27 @@ export const createWrapper = ( : body ? JSON.stringify(body) : undefined, - }; + } const response = await getRuntimeFetch()( baseURL + url + queryString, fetchOptions, - ); - return responseInterceptor(response); - }, - get(url: string, options?: { params?: Record | null }) { - return this.request(url, { method: 'GET', ...options }); + ) + // The operation's generated contract owns the response type at this HTTP boundary. + return (await responseInterceptor(response, datePlan)) as T }, post( url: string, options?: { - body?: any; - formData?: UniversalFormData; - params?: Record | null; - }, - ) { - return this.request(url, { method: 'POST', ...options }); - }, - put( - url: string, - options?: { - body?: any; - formData?: UniversalFormData; - params?: Record | null; + body?: any + formData?: UniversalFormData + params?: Record | null }, ) { - return this.request(url, { method: 'PUT', ...options }); - }, - delete(url: string, options?: { params?: Record | null }) { - return this.request(url, { method: 'DELETE', ...options }); + return this.request(url, { method: 'POST', ...options }) }, - }; + } - return client; -}; + return client +} -export type WrapperClient = ReturnType; +export type WrapperClient = ReturnType diff --git a/test-d/legacy-package-exports.cts b/test-d/legacy-package-exports.cts new file mode 100644 index 0000000..6dc2a04 --- /dev/null +++ b/test-d/legacy-package-exports.cts @@ -0,0 +1,12 @@ +import Facturapi = require('..') + +const client = new Facturapi('sk_test_123') +const invoice: Promise = client.invoices.retrieve('inv_123') +void invoice +const invoiceType: Facturapi.InvoiceType = Facturapi.InvoiceType.INGRESO +const invoices: Promise> = + client.invoices.list() +void [invoiceType, invoices] + +const legacy = new Facturapi.default('sk_test_123') +void legacy diff --git a/test-d/package-exports.cts b/test-d/package-exports.cts new file mode 100644 index 0000000..21fc4d6 --- /dev/null +++ b/test-d/package-exports.cts @@ -0,0 +1,12 @@ +import Facturapi = require('facturapi') + +const client = new Facturapi('sk_test_123') +const invoice: Promise = client.invoices.retrieve('inv_123') +void invoice +const invoiceType: Facturapi.InvoiceType = Facturapi.InvoiceType.INGRESO +const invoices: Promise> = + client.invoices.list() +void [invoiceType, invoices] + +const legacy = new Facturapi.default('sk_test_123') +void legacy diff --git a/test-d/package-exports.mts b/test-d/package-exports.mts new file mode 100644 index 0000000..96f79bb --- /dev/null +++ b/test-d/package-exports.mts @@ -0,0 +1,5 @@ +import Facturapi, { type Invoice } from 'facturapi' + +const client = new Facturapi('sk_test_123') +const invoice: Promise = client.invoices.retrieve('inv_123') +void invoice diff --git a/test-d/runtime-types.test-d.ts b/test-d/runtime-types.test-d.ts index bd5ab13..ade704b 100644 --- a/test-d/runtime-types.test-d.ts +++ b/test-d/runtime-types.test-d.ts @@ -1,22 +1,209 @@ -import { expectAssignable, expectType, expectError } from 'tsd' +import { + expectAssignable, + expectNotAssignable, + expectType, + expectError, +} from 'tsd' import Facturapi, { BinaryDownload, + ApiKeys, + ApiEvent, CursorSearchParams, + Customer, PageSearchParams, FacturapiError, Invoice, + InvoiceDraft, + CustomerInfo, + CancelInvoiceOptions, + CustomerNationalCreateInput, + CustomerForeignCreateInput, + CustomerGenericCreateInput, + InvoiceCreateInput, + InvoiceNominaEditInput, + NominaPercepcionInput, + NominaEntidadSncfInput, + NominaEmisorInput, + NominaHorasExtraInput, + BaseTax, + TaxType, + IepsMode, + CartaPorteAutotransporte, InvoiceItem, InvoiceType, IssuingType, NodeLikeReadableStream, + Organization, + OrganizationInvite, + OrganizationTeamRole, + OrganizationUserAccess, + PagoComplementData, + Product, + Receipt, + Retention, SearchResult, SignedDownloadUrl, TaxFactor, + ToInvoiceSummary, + Webhook, ZipRequest, } from '../dist' const client = new Facturapi('sk_test_123') +declare const createdInvoice: Awaited> +expectAssignable(createdInvoice) +expectAssignable(createdInvoice.date) +expectAssignable(createdInvoice.stamp) + +expectAssignable({ type: 'N' }) +expectError({ type: 'P' }) +expectAssignable({ + status: 'draft', + complements: [ + { + type: 'leyendas_fiscales', + data: { leyendas: [{ texto_leyenda: 'Ejemplo' }] }, + }, + ], +}) +expectAssignable({ + tipo_percepcion: '001', + clave: 'ABC', + importe_gravado: 1, + importe_exento: 0, +}) +expectError({ + tipo_percepcion: '019', + clave: 'ABC', + importe_gravado: 1, + importe_exento: 0, +}) +expectError({ tipo_percepcion: '001', clave: 'ABC' }) +expectAssignable({ + tipo_percepcion: '019', + clave: 'ABC', + importe_gravado: 1, + importe_exento: 0, + horas_extra: [ + { dias: 1, tipo_horas: '01', horas_extra: 1, importe_pagado: 1 }, + ], +}) +expectError({ + dias: 1, + tipo_horas: '01', + horas_extra: 1, +}) +expectAssignable({ + origen_recurso: 'IM', + monto_recurso_propio: 1, +}) +expectAssignable({ origen_recurso: 'IF' }) +expectError({ origen_recurso: 'IM' }) +expectError({ entidad_sncf: { origen_recurso: 'IM' } }) +expectError( + client.invoices.create({ + type: 'P', + customer: 'cus', + complements: [{ type: 'pago', data: { tipo_nomina: 'O' } }], + }), +) +expectError({ + type: 'P', + customer: 'cus', + payment_method: 'PPD', + complements: [], +}) +client.invoices.updateDraft('draft', { type: 'N' }) +expectAssignable({ + type: TaxType.IEPS, + rate: 0.08, + ieps_mode: IepsMode.UNIT, +}) +expectError({ + PermSCT: 'TPAF01', + NumPermisoSCT: 'Example', +}) + +expectAssignable({ status: 'draft', date: new Date() }) +expectAssignable({ type: 'E', status: 'draft' }) +expectAssignable({ type: 'P', status: 'draft' }) +expectAssignable({ type: 'N', status: 'draft' }) +expectAssignable({ type: 'T', status: 'draft' }) +expectError({ type: 'I', status: 'pending' }) +expectError({ type: 'E', status: 'pending' }) +expectError({ type: 'P', status: 'pending' }) +expectError({ type: 'N', status: 'pending' }) +expectError({ type: 'T', status: 'pending' }) +expectError({}) +declare const invoiceInput: InvoiceCreateInput +if (invoiceInput.status !== 'draft') { + expectNotAssignable(invoiceInput.customer) + if (invoiceInput.type === 'P') { + expectNotAssignable(invoiceInput.complements) + } +} +expectAssignable({ + status: 'draft', + date: '2026-09-30T12:00:00Z', +}) +expectAssignable({ + customer: 'cus', + payment_form: '28', + items: [ + { + quantity: 1, + product: { description: 'Ejemplo', product_key: '60131324', price: 1 }, + }, + ], +}) +expectAssignable({ + status: 'draft', + customer: null, + payment_form: null, + use: null, +}) +client.invoices.updateDraft('draft', { type: 'E', customer: null }) +expectError({ type: 'N', customer: null }) +client.invoices.create({ + type: 'P', + customer: 'cus', + complements: [ + { + type: 'pago', + data: { + payment_form: '28', + related_documents: [ + { + uuid: '39c85a3f-275b-4341-b259-e8971d9f8a94', + amount: 1, + installment: 1, + last_balance: 1, + taxes: [], + }, + ], + }, + }, + ], +}) +expectError( + client.webhooks.create({ + url: 'https://example.com/webhook', + enabled_events: ['*'], + secret: 'caller-secret', + }), +) +expectType>( + client.receipts.toInvoice({ keys: ['receipt-key'] }), +) +expectType>( + client.receipts.toInvoice({ keys: ['receipt-key'], dry_run: true }), +) +declare const dryRun: boolean +expectType>( + client.receipts.toInvoice({ keys: ['receipt-key'], dry_run: dryRun }), +) + const zipPromise = client.invoices.downloadZip('inv_123') expectType>(zipPromise) @@ -46,7 +233,7 @@ expectType>( declare const signedDownloadUrl: SignedDownloadUrl expectType(signedDownloadUrl.url) -expectType(signedDownloadUrl.expires_at) +expectType(signedDownloadUrl.expires_at) expectType(signedDownloadUrl.content_type) expectType(signedDownloadUrl.filename) expectType>( @@ -107,7 +294,75 @@ if ('pipe' in binary && typeof binary.pipe === 'function') { expectAssignable(TaxFactor.EXENTO) declare const invoiceItem: InvoiceItem -expectType(invoiceItem.property_tax_account) +expectType(invoiceItem.property_tax_account) + +declare const invoice: Invoice +expectType(invoice.created_at) +expectType(invoice.date) +expectType(invoice.canceled_at) +expectError(invoice.cancellation) +expectType(invoice.stamp?.date) + +declare const receipt: Receipt +expectType(receipt.created_at) +expectType(receipt.date) +expectType(receipt.expires_at) + +declare const customer: Customer +expectType(customer.created_at) +expectType(customer.sat_validated_at) +expectType(customer.edit_link_expires_at) +declare const product: Product +expectType(product.created_at) +declare const organization: Organization +expectType(organization.created_at) +expectType(organization.certificate.expires_at) +expectType(organization.pending_add_ons_update?.scheduled_for) +declare const draftResponse: InvoiceDraft +expectAssignable(null) +expectType(draftResponse.customer) +expectError( + client.webhooks.create({ + url: 'https://example.com/hooks', + enabled_events: ['*'], + }), +) +expectError( + client.webhooks.update('hook_example', { + status: 'enabled', + enabled_events: ['*'], + }), +) +declare const webhook: Webhook +expectAssignable[number]>('*') +expectType(webhook.created_at) +declare const event: ApiEvent +expectType(event.created_at) +declare const payment: PagoComplementData +expectType(payment.date) +expectType<'01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' | undefined>( + payment.related_documents[0].taxability, +) +declare const zipRequest: ZipRequest +expectType(zipRequest.created_at) +expectType(zipRequest.scheduled_at) +expectError(zipRequest.updated_at) + +declare const retention: Retention +expectType(retention.fecha_exp) +expectType(retention.stamp?.date) + +declare const apiKey: ApiKeys +expectType(apiKey.created_at) +declare const access: OrganizationUserAccess +expectType(access.created_at) +expectType(access.updated_at) +declare const invite: OrganizationInvite +expectType(invite.created_at) +expectType(invite.expires_at) +declare const role: OrganizationTeamRole +expectType(role.created_at) +expectType(role.updated_at) declare const apiError: FacturapiError expectType(apiError.status) @@ -139,3 +394,246 @@ expectType>( expectType>( client.invoices.list({ after: 'token' }).then((result) => result.next_cursor), ) + +declare const paymentSummary: Awaited< + ReturnType +> +expectAssignable( + paymentSummary, +) +expectNotAssignable< + PagoComplementData['related_documents'][number]['taxability'] +>(1) + +// Incomplete customer information is accepted only when an edit link is requested. +client.customers.create({}, { createEditLink: true }) +client.customers.create( + { email: 'cliente@example.com' }, + { createEditLink: true }, +) +client.customers.create( + { address: { city: 'Hermosillo' } }, + { createEditLink: true }, +) +expectError(client.customers.create({})) +expectError(client.customers.create({}, { createEditLink: false })) +expectError( + client.customers.create({}, { createEditLink: Math.random() > 0.5 }), +) +expectError(client.customers.create({ address: { zip: '83200' } })) +expectError(client.customers.create({ email: 123 }, { createEditLink: true })) + +// Country and RFC variants preserve the requirements of customer creation. +client.customers.create({ + legal_name: 'Cliente nacional', + tax_id: 'ABC101010111', + tax_system: '601', + address: { zip: '83200' }, +}) +client.customers.create({ + legal_name: 'Foreign customer', + address: { country: 'USA' }, +}) +client.customers.create({ + legal_name: 'Foreign customer', + tax_id: null, + tax_system: null, + address: { country: 'USA' }, +}) +client.customers.create({ + legal_name: 'PUBLICO EN GENERAL', + tax_id: 'XAXX010101000', +}) +expectNotAssignable({ + legal_name: 'Cliente', + tax_system: '601', + address: { zip: '83200' }, +}) +expectNotAssignable({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + address: { zip: '83200' }, +}) +expectNotAssignable({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + tax_system: '601', + address: {}, +}) +expectNotAssignable({ + legal_name: 'Foreign', + tax_system: '601', + address: { country: 'USA' }, +}) +expectNotAssignable({ + legal_name: 'Publico', + tax_id: 'XAXX010101000', + tax_system: '601', +}) +expectError(client.customers.create({ legal_name: 'Foreign', address: {} })) + +// A default period needs no fields; explicit receipt selection needs both dates. +client.receipts.createGlobalInvoice({}) +client.receipts.createGlobalInvoice({ + receipts: ['rec_ejemplo'], + from: '2026-01-01', + to: new Date(), +}) +expectError(client.receipts.createGlobalInvoice({ receipts: ['rec_ejemplo'] })) +expectError( + client.receipts.createGlobalInvoice({ + receipts: ['rec_ejemplo'], + from: new Date(), + }), +) + +// Draft deletion needs no query; replacement motives need a substitution. +client.invoices.cancel('inv_ejemplo') +client.retentions.cancel('ret_ejemplo') +client.invoices.cancel('inv_ejemplo', { motive: '02' }) +client.retentions.cancel('ret_ejemplo', { motive: '03' }) +client.invoices.cancel('inv_ejemplo', { + motive: '01', + substitution: 'inv_sustituto', +}) +client.retentions.cancel('ret_ejemplo', { + motive: '04', + substitution: 'ret_sustituto', +}) +expectError(client.invoices.cancel('inv_ejemplo', { motive: '01' })) +expectError(client.invoices.cancel('inv_ejemplo', { motive: '04' })) +expectError(client.retentions.cancel('ret_ejemplo', { motive: '01' })) +expectError(client.retentions.cancel('ret_ejemplo', { motive: '04' })) +expectError( + client.invoices.cancel('inv_ejemplo', { substitution: 'inv_sustituto' }), +) +expectError( + client.customers.create({ + legal_name: undefined, + address: { country: 'USA' }, + }), +) +expectNotAssignable({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + tax_system: undefined, + address: { zip: '83200' }, +}) +expectNotAssignable({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + tax_system: '601', + address: { zip: undefined }, +}) +expectError( + client.receipts.createGlobalInvoice({ + receipts: ['rec_ejemplo'], + from: undefined, + to: undefined, + }), +) + +// Existing public aliases use the same conditional contract as the method. +expectNotAssignable({ motive: '01' }) +expectAssignable({ + motive: '04', + substitution: 'inv_sustituto', +}) +declare const customerWithIncompleteFiscalInfo: Customer +expectType(customerWithIncompleteFiscalInfo.tax_id) +expectType( + customerWithIncompleteFiscalInfo.tax_system, +) +expectType(customerWithIncompleteFiscalInfo.phone) +expectType( + customerWithIncompleteFiscalInfo.edit_link_expires_at, +) +client.customers.create({ tax_id: null }, { createEditLink: true }) +client.customers.update('cus_ejemplo', { phone: null }) +expectError( + client.customers.create({ tax_system: null }, { createEditLink: true }), +) + +// Explicit creation methods select their own contract without narrowing a free country string. +client.customers.createNational({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + tax_system: '601', + address: { zip: '83200' }, +}) +client.customers.createForeign({ + legal_name: 'Foreign', + address: { country: 'USA' }, +}) +client.customers.createForeign({ + legal_name: 'Foreign', + address: { country: 'MEX' }, +}) +client.customers.createGeneric({ + legal_name: 'Publico', + tax_id: 'XAXX010101000', +}) +client.customers.createGeneric({ + legal_name: 'Generic foreign', + tax_id: 'XEXX010101000', +}) +expectError( + client.customers.createNational({ + legal_name: 'Cliente', + tax_system: '601', + address: { country: 'MEX', zip: '83200' }, + }), +) +expectError( + client.customers.createNational({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + address: { zip: '83200' }, + }), +) +expectError( + client.customers.createNational({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + tax_system: '601', + address: {}, + }), +) +expectError( + client.customers.createForeign({ legal_name: 'Foreign', address: {} }), +) +expectError( + client.customers.createGeneric({ + legal_name: 'Cliente', + tax_id: 'ABC101010111', + }), +) +expectError( + client.customers.createGeneric({ + legal_name: 'Publico', + tax_id: 'XAXX010101000', + tax_system: '601', + }), +) +// Incomplete creation remains an explicit option of the general method. +expectError(client.customers.createNational({}, { createEditLink: true })) +client.customers.create({}, { createEditLink: true }) + +// Updating a product does not require resending its creation fields. +client.products.update('prod_ejemplo', { price: 456.7 }) +client.products.update('prod_ejemplo', { description: 'Actualizado' }) +expectError( + client.products.update('prod_ejemplo', { email: 'jdoe@example.com' }), +) +expectError(client.products.create({ price: 456.7 })) + +// Native Node streams are valid upload inputs without casts. +import type { ReadStream } from 'node:fs' +declare const nativeReadStream: ReadStream +client.organizations.uploadLogo('org_ejemplo', nativeReadStream) +client.organizations.uploadCertificate( + 'org_ejemplo', + nativeReadStream, + nativeReadStream, + 'example-password', +) diff --git a/test/browser/runtime-smoke.browser.spec.ts b/test/browser/runtime-smoke.browser.spec.ts index 57e7940..887d87d 100644 --- a/test/browser/runtime-smoke.browser.spec.ts +++ b/test/browser/runtime-smoke.browser.spec.ts @@ -11,7 +11,7 @@ test.describe('browser smoke (real chromium)', () => { let latestUploadContentType: string | undefined; test.beforeAll(async () => { - const distPath = join(process.cwd(), 'dist', 'index.es.js'); + const distPath = join(process.cwd(), 'dist', 'index.mjs'); const bundle = await readFile(distPath, 'utf8'); server = createServer(async (req: IncomingMessage, res: ServerResponse) => { @@ -25,7 +25,7 @@ test.describe('browser smoke (real chromium)', () => {