diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml new file mode 100644 index 000000000..f93e68258 --- /dev/null +++ b/.github/workflows/openapi.yml @@ -0,0 +1,33 @@ +name: OpenAPI contract + +on: + pull_request: + paths: + - website/openapi_v2*.yaml + - website/scripts/check-openapi.mjs + - website/test/openapi-types.fixture.txt + - website/package.json + - website/pnpm-lock.yaml + - website/pnpm-workspace.yaml + - .github/workflows/openapi.yml + push: + branches: [main] + workflow_dispatch: + +jobs: + contract: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 11.5.1 + - uses: actions/setup-node@v4 + with: + node-version: 24.x + cache: pnpm + cache-dependency-path: website/pnpm-lock.yaml + - run: pnpm install --frozen-lockfile + working-directory: website + - run: pnpm test:openapi + working-directory: website diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..94611048c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,28 @@ +# AGENTS.md + +## Public documentation and confidentiality + +- This is a public repository. Publish only the intended public API contract and + information authorized for public documentation. +- Private sources may be consulted to verify API behavior. Never publish their + source code, internal file paths, commit hashes, implementation details, + private data, or internal plans in files, commit messages, pull requests, + review comments, issues, or CI output. +- Keep evidence from private sources in private files or repositories. Explain + public corrections in terms of observable API behavior without citing private + implementation sources. +- Keep PR titles and descriptions focused on the documentation change. Omit + unrelated internal plans and conversational context. +- Before committing or publishing, review the full diff, commit messages, and + accompanying descriptions for confidential information. +- If confidential information was published, a later deletion commit is not + sufficient. Clean affected branch history, verify remote references, and + explicitly report any host-side references or cached copies that remain. + +## API contract changes + +- Verify changes to types, required fields, defaults, authentication, parameters, + and status codes against authoritative sources. Do not treat an SDK declaration + or a review comment alone as proof of API behavior. +- Keep the Spanish and English OpenAPI contracts structurally aligned. +- Run the relevant repository checks for specification changes. diff --git a/website/docs/getting-started/install.mdx b/website/docs/getting-started/install.mdx index 32b787601..007acfe65 100644 --- a/website/docs/getting-started/install.mdx +++ b/website/docs/getting-started/install.mdx @@ -77,12 +77,12 @@ Importa la librería antes de usarla. -CommonJS ```javascript -import Facturapi from 'facturapi' +const Facturapi = require('facturapi'); ``` -ESM / Typescript +ESM / TypeScript + ```javascript import Facturapi from 'facturapi'; ``` diff --git a/website/docs/guides/invoices/cancelaciones.mdx b/website/docs/guides/invoices/cancelaciones.mdx index 856aa1a68..5da3717bb 100644 --- a/website/docs/guides/invoices/cancelaciones.mdx +++ b/website/docs/guides/invoices/cancelaciones.mdx @@ -188,10 +188,14 @@ import fs from 'node:fs'; const facturapi = new Facturapi('sk_test_API_KEY'); const xmlStream = await facturapi.invoices.downloadCancellationReceiptXml('58e93bd8e86eb318b019743d'); -xmlStream.pipe(fs.createWriteStream('acuse_cancelacion.xml')); +if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(fs.createWriteStream('acuse_cancelacion.xml')); +} const pdfStream = await facturapi.invoices.downloadCancellationReceiptPdf('58e93bd8e86eb318b019743d'); -pdfStream.pipe(fs.createWriteStream('acuse_cancelacion.pdf')); +if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(fs.createWriteStream('acuse_cancelacion.pdf')); +} ``` diff --git a/website/docs/quickstart.mdx b/website/docs/quickstart.mdx index 314520577..4771488ec 100644 --- a/website/docs/quickstart.mdx +++ b/website/docs/quickstart.mdx @@ -373,9 +373,13 @@ import fs from 'fs'; const zipStream = await facturapi.invoices.downloadZip(invoice.id); // Guarda la descarga en un archivo const file = fs.createWriteStream('./factura.zip'); -zipStream.pipe(file); +if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(file); +} // O envíalo como respuesta a tu cliente (en ExpressJS) -zipStream.pipe(res); +if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(res); +} ``` diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index d541e9af6..709f1f74f 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -62,7 +62,7 @@ const darkCodeTheme = require("prism-react-renderer").themes.dracula; }, options: { disableSearch: true, - requiredPropsFirst: true, + sortRequiredPropsFirst: true, noAutoAuth: true, }, }, diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/getting-started/install.mdx b/website/i18n/en/docusaurus-plugin-content-docs/current/getting-started/install.mdx index 148fddad0..1a9207f99 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/getting-started/install.mdx +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/getting-started/install.mdx @@ -77,12 +77,12 @@ Import the library before using it in your code. -CommonJS ```javascript -import Facturapi from 'facturapi' +const Facturapi = require('facturapi'); ``` -ESM / Typescript +ESM / TypeScript + ```javascript import Facturapi from 'facturapi'; ``` diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/guides/invoices/cancelaciones.mdx b/website/i18n/en/docusaurus-plugin-content-docs/current/guides/invoices/cancelaciones.mdx index d279076ea..53cf66e3f 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/guides/invoices/cancelaciones.mdx +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/guides/invoices/cancelaciones.mdx @@ -174,10 +174,14 @@ import fs from 'node:fs'; const facturapi = new Facturapi('sk_test_API_KEY'); const xmlStream = await facturapi.invoices.downloadCancellationReceiptXml('58e93bd8e86eb318b019743d'); -xmlStream.pipe(fs.createWriteStream('cancellation_receipt.xml')); +if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(fs.createWriteStream('cancellation_receipt.xml')); +} const pdfStream = await facturapi.invoices.downloadCancellationReceiptPdf('58e93bd8e86eb318b019743d'); -pdfStream.pipe(fs.createWriteStream('cancellation_receipt.pdf')); +if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(fs.createWriteStream('cancellation_receipt.pdf')); +} ``` diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart.mdx b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart.mdx index 70aea933f..4a05096b6 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart.mdx +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart.mdx @@ -332,9 +332,13 @@ import fs from 'fs'; const zipStream = await facturapi.invoices.downloadZip(invoice.id); // Save the downloaded file to disk const file = fs.createWriteStream('./factura.zip'); -zipStream.pipe(file); +if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(file); +} // Or send it as a response to your customer (ExpressJS syntax) -zipStream.pipe(res); +if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(res); +} ``` diff --git a/website/openapi_v2.en.yaml b/website/openapi_v2.en.yaml index 43ca827de..bccc5a428 100644 --- a/website/openapi_v2.en.yaml +++ b/website/openapi_v2.en.yaml @@ -28,7 +28,7 @@ info: authentication, and verbs. During development, you can use the Facturapi API in the Test environment, and the invoices you issue will not be sent to the SAT (Mexican Tax Authority) and will not have fiscal validity. - + The secret key you use to authenticate will determine both the environment in which the invoice will be created (Test or Live), as well as the organization to use as the issuer of your invoice or as the owner of the resource you request to create. Send `Accept-Language: en` for English Facturapi error messages, or @@ -66,7 +66,7 @@ tags: x-displayName: Keys from SAT's catálogos description: | These are the main catalogs from SAT, included here for convenience. This is by no means the full list. You can find these and more catalogs on the official SAT website: http://omawww.sat.gob.mx/tramitesyservicios/Paginas/anexo_20_version3-3.htm - + ### Forma de Pago (Payment Form) @@ -108,7 +108,7 @@ tags: ### Uso del CFDI (CFDI use) - + Key | Description (Spanish) | Description (English) | Allowed Fiscal Regimes :-----:|:----------- |:----------- |:----------- "G01" | Adquisición de mercancías. | Purchase of goods | 601, 603, 606, 612, 620, 621, 622, 623, 624, 625, 626 @@ -985,11 +985,12 @@ x-tagGroups: - receipt_model - retention_model - organization_model - + paths: /catalogs/cartaporte/3.1/air-transport-codes: get: + operationId: "searchCartaPorteAirTransportCodes" tags: - carta_porte_keys summary: Search air transport codes @@ -1047,10 +1048,9 @@ paths: ["limit"] = 10 }); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - + - $ref: '#/components/parameters/SearchPagination' + - $ref: '#/components/parameters/SearchAfter' + - $ref: '#/components/parameters/SearchBefore' - in: query name: q schema: @@ -1062,7 +1062,6 @@ paths: schema: type: integer minimum: 1 - required: false description: Page of results to return, starting from page 1. The maximum is not fixed; together with `limit` it must fit within the 3,000-result cap. - in: query name: limit @@ -1070,7 +1069,6 @@ paths: type: integer minimum: 1 maximum: 100 - required: false description: Number from 1 to 100 representing the maximum amount of results to return for pagination purposes. responses: '200': @@ -1078,10 +1076,21 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/SearchKeyDescriptionResult" + $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/transport-configs: get: + operationId: "searchCartaPorteTransportConfigs" tags: - carta_porte_keys summary: Search auto transport configurations @@ -1168,9 +1177,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/comercioexterior/2.0/tariff-fractions: get: + operationId: "searchComercioExteriorTariffFractions" tags: - comercio_exterior_keys summary: Search tariff fractions @@ -1227,10 +1247,9 @@ paths: ["limit"] = 10 }); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - + - $ref: '#/components/parameters/SearchPagination' + - $ref: '#/components/parameters/SearchAfter' + - $ref: '#/components/parameters/SearchBefore' - in: query name: q schema: @@ -1242,7 +1261,6 @@ paths: schema: type: integer minimum: 1 - required: false description: Page of results to return, starting from page 1. The maximum is not fixed; together with `limit` it must fit within the 3,000-result cap. - in: query name: limit @@ -1250,7 +1268,6 @@ paths: type: integer minimum: 1 maximum: 100 - required: false description: Number from 1 to 100 representing the maximum amount of results to return for pagination purposes. responses: '200': @@ -1272,6 +1289,7 @@ paths: /catalogs/cartaporte/3.1/rights-of-passage: get: + operationId: "searchCartaPorteRightsOfPassage" tags: - carta_porte_keys summary: Search rights of passage @@ -1358,9 +1376,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/customs-documents: get: + operationId: "searchCartaPorteCustomsDocuments" tags: - carta_porte_keys summary: Search customs documents @@ -1447,9 +1476,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/packaging-types: get: + operationId: "searchCartaPortePackagingTypes" tags: - carta_porte_keys summary: Search packaging types @@ -1536,9 +1576,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/trailer-types: get: + operationId: "searchCartaPorteTrailerTypes" tags: - carta_porte_keys summary: Search trailer types @@ -1625,9 +1676,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/hazardous-materials: get: + operationId: "searchCartaPorteHazardousMaterials" tags: - carta_porte_keys summary: Search hazardous materials @@ -1714,9 +1776,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/naval-authorizations: get: + operationId: "searchCartaPorteNavalAuthorizations" tags: - carta_porte_keys summary: Search naval authorizations @@ -1803,7 +1876,7 @@ paths: application/json: schema: allOf: - - $ref: "#/components/schemas/SearchResult" + - $ref: '#/components/schemas/SearchResult' - type: object properties: data: @@ -1813,9 +1886,20 @@ paths: properties: key: type: string + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/port-stations: get: + operationId: "searchCartaPortePortStations" tags: - carta_porte_keys summary: Search port stations @@ -1902,9 +1986,20 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/marine-containers: get: + operationId: "searchCartaPorteMarineContainers" tags: - carta_porte_keys summary: Search marine containers @@ -1991,6 +2086,16 @@ paths: application/json: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthenticated' + '404': + $ref: '#/components/responses/NotFound' + '429': + $ref: '#/components/responses/RateLimited' + '500': + $ref: '#/components/responses/UnexpectedError' /customers: post: operationId: createCustomer @@ -2007,7 +2112,7 @@ paths: Once the customer is created and a response object is obtained, we recommend saving the ID in your database along with the customer information. Later, you can call the Create Invoice endpoint by passing the customer ID instead of repeating the information. - + Finally, keep in mind that the customers you create in the Test environment **are not shared** with the Live environment. x-codeSamples: @@ -2096,9 +2201,10 @@ paths: description: | If set to `true`, the response will include a link you can share with the customer to allow them to edit their information. This link will be available from the `edit_link` field, - will be valid for 7 days and can only be used once. + will be valid for 3 days and can only be used once. Additionally, setting this parameter to `true` will skip the validation of the customer's fiscal data, allowing you to create customers with incomplete information. + With `true`, the request body follows `CustomerCreateWithEditLinkInput`; otherwise it follows `CustomerCreateInput`. security: - "SecretLiveKey": [] - "SecretTestKey": [] @@ -2384,7 +2490,7 @@ paths: description: | If set to `true`, the response will include a link you can share with the customer to allow them to edit their information. This link will be available from the `edit_link` field, - will be valid for 7 days and can only be used once. + will be valid for 3 days and can only be used once. Setting this parameter to `true` while editing a customer will **not** skip the validation of the customer's fiscal data. requestBody: @@ -2481,7 +2587,7 @@ paths: description: | Sends a link for the customer to edit their fiscal information. - This link will be available in the `edit_link` field, valid for 7 days and can only be used once. + This link will be available in the `edit_link` field, valid for 3 days and can only be used once. x-codeSamples: - lang: Bash label: cURL @@ -2577,7 +2683,7 @@ paths: Validates that the customer's fiscal information matches the SAT records. Its main function is to validate that the registered customer data continues to meet the SAT validation. - + > **Note:** > The operations of creating a customer, editing a customer, and creating an invoice already perform a > validation of the customer's information, so it is **not** necessary to call this endpoint @@ -2957,10 +3063,7 @@ paths: const product = await facturapi.products.update( '590e22c26d04f840aa8438b2', { - email: 'jdoe@example.com', - address: { - street: 'Santa Monica Ave.' - } + price: 456.70 } ); - lang: csharp @@ -3255,12 +3358,9 @@ paths: content: application/json: schema: - type: object - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/Invoice" - draft: "#/components/schemas/InvoiceDraft" + anyOf: + - $ref: "#/components/schemas/Invoice" + - $ref: "#/components/schemas/InvoiceDraft" "202": description: Request accepted; Facturapi will try to recover the CFDI up to five times, once every 10 minutes content: @@ -3286,7 +3386,7 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - + get: operationId: listInvoices tags: @@ -3324,16 +3424,16 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // All invoices from the organization - const invoiceSearch = await facturapi.invoices.list(); + const invoiceSearch1 = await facturapi.invoices.list(); // All invoices issued to a certain customer - const invoiceSearch = await facturapi.invoices.list({ + const invoiceSearch2 = await facturapi.invoices.list({ customer: '590ce6c56d04f840aa8438af' }); // Page 3 of the search results for free text // of invoices issued to a certain customer between 2017 and 2019 - const invoiceSearch = await facturapi.invoices.list({ + const invoiceSearch3 = await facturapi.invoices.list({ q: 'Aspiradora Robot', customer: '590ce6c56d04f840aa8438af', date: { @@ -3448,11 +3548,11 @@ paths: schema: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: Filter by invoice type. Exact match. - in: query name: payment_method @@ -3549,58 +3649,30 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests: - post: - operationId: createInvoiceZipRequest + /invoices/{invoice_id}: + get: + operationId: getInvoice tags: - invoice - summary: Create or retrieve a monthly ZIP request - description: | - Creates a request to generate a ZIP file containing one month of invoices, or retrieves the existing request with the same filters. - - This operation is idempotent. Invoice types are normalized, so `["I", "E"]` and `["E", "I"]` resolve to the same request. Identical concurrent calls also return the same request. - - If an earlier request has a `failed` status, calling this method again retries it. Before retrying, the previous error and task fields, processed progress, and failed-document list are cleared. If scheduling fails, the request is saved with a `failed` status and the API returns a `5xx` error. - - This method requires a live-mode organization API key, an active subscription, and permission to read invoices. Test-mode keys return HTTP 402. + summary: Retrieve invoice by ID + description: Returns the `Invoice` object with the specified ID. If the invoice does not exist, a 404 error will be returned. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests \ - -H "Authorization: Bearer sk_live_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "year": 2025, - "month": 3, - "issuer_type": "issuing", - "invoice_types": ["I", "E"] - }' + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequest = await facturapi.invoices.createZipRequest({ - year: 2025, - month: 3, - issuer_type: 'issuing', - invoice_types: ['I', 'E'] - }); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.retrieve('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequest = await facturapi.Invoice.CreateZipRequestAsync( - new Dictionary - { - ["year"] = 2025, - ["month"] = 3, - ["issuer_type"] = "issuing", - ["invoice_types"] = new[] { "I", "E" } - } - ); + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.RetrieveAsync("58e93bd8e86eb318b019743d"); - lang: Java label: Java source: | @@ -3608,497 +3680,450 @@ paths: import java.util.List; import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequest = facturapi.invoices().createZipRequest( - Map.of( - "year", 2025, - "month", 3, - "issuer_type", "issuing", - "invoice_types", List.of("I", "E") - ) - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().retrieve( + "inv_123" + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequest = $facturapi->Invoices->createZipRequest([ - "year" => 2025, - "month" => 3, - "issuer_type" => "issuing", - "invoice_types" => ["I", "E"] - ]); - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/InvoiceZipRequestCreateInput" + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->retrieve( "58e93bd8e86eb318b019743d" ); + parameters: + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID of the invoice security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: ZIP request created or retrieved successfully. + description: "`Invoice` object" content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequest" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNoInvoices" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - get: - operationId: listInvoiceZipRequests + put: + operationId: updateDraftInvoice tags: - invoice - summary: List monthly ZIP requests + summary: Edit draft invoice description: | - Returns a paginated list of ZIP requests. `year` and `month` must be provided together. `invoice_types` filters by one type or an exact normalized array. + Updates the information of a draft invoice, setting only the values for + the paramenters that are sent. Undefined values will not be modified. - This method requires a live-mode organization API key, an active subscription, and permission to read invoices. + In the `Invoice` response object, Facturapi will automatically assign the + `is_ready_to_stamp` field with the value `true` if the invoice passes the + minimum validation required to be stamped; otherwise, the + `is_ready_to_stamp` field will be `false`. x-codeSamples: - lang: Bash label: cURL source: | - curl "https://www.facturapi.io/v2/invoices/zip-requests?year=2025&month=3&status=finished&limit=20&page=1" \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + -X PUT \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "payment_form": "06" + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequests = await facturapi.invoices.listZipRequests({ - year: 2025, - month: 3, - status: 'finished', - limit: 20, - page: 1 - }); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.updateDraft( + '58e93bd8e86eb318b019743d', + { + payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO + } + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequests = await facturapi.Invoice.ListZipRequestsAsync( + var facturapi = new Facturapi("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.UpdateDraftAsync( + "58e93bd8e86eb318b019743d", new Dictionary { - ["year"] = 2025, - ["month"] = 3, - ["status"] = "finished", - ["limit"] = 20, - ["page"] = 1 + ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO } ); - lang: Java label: Java source: | import io.facturapi.Facturapi; + import java.util.List; import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequests = facturapi.invoices().listZipRequests( - Map.of( - "year", 2025, - "month", 3, - "status", "finished", - "limit", 20, - "page", 1 - ) - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().updateDraft("inv_123", Map.of( + "items", List.of( + Map.of( + "quantity", 1, + "product", "prod_123" + ) + ) + )); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequests = $facturapi->Invoices->listZipRequests([ - "year" => 2025, - "month" => 3, - "status" => "finished", - "limit" => 20, - "page" => 1 + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->updateDraft("58e93bd8e86eb318b019743d", [ + "payment_form" => \Facturapi\PaymentForm::EFECTIVO ]); parameters: - - in: query - name: year - schema: - type: integer - minimum: 2000 - maximum: 9999 - description: Year to filter. Must be provided with `month`. - - in: query - name: month - schema: - type: integer - minimum: 1 - maximum: 12 - description: Month to filter. Must be provided with `year`. - - in: query - name: status - schema: - $ref: "#/components/schemas/InvoiceZipRequestStatus" - description: ZIP request status. - - in: query - name: issuer_type - schema: - $ref: "#/components/schemas/IssuingType" - description: Filters issued or received invoices. - - in: query - name: invoice_types - schema: - type: array - uniqueItems: true - items: - $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" - description: Filters by one invoice type or an exact normalized array. - - in: query - name: page + - in: path + name: invoice_id schema: - type: integer - minimum: 1 - default: 1 - description: Results page, starting at 1. - - $ref: "#/components/parameters/SearchLimit" + type: string + required: true + description: ID of the invoice to edit + requestBody: + $ref: "#/components/requestBodies/InvoiceEdit" security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Paginated ZIP request results. + description: "`Invoice` object edited successfully" content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequestSearchResult" + $ref: "#/components/schemas/InvoiceDraft" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}: - get: - operationId: retrieveInvoiceZipRequest + delete: + operationId: cancelInvoice tags: - invoice - summary: Retrieve a monthly ZIP request + summary: Cancel invoice description: | - Retrieves a ZIP request. Poll this method until the status becomes `finished` or `failed`. Once it is `finished`, call the download method. + Creates a cancellation request to the SAT for the specified invoice, using the **SAT's new cancellation scheme (effective since 2022)**. - Requires a live-mode organization API key, an active subscription, and permission to read invoices. + When using this method, the following results can occur: + + - The call returns an error with the explanation of why the cancellation could not be completed. + - The call is successful and returns an `invoice` object with the property `status: "canceled"` (the cancellation has already been accepted by the SAT). + - The call is successful, but the cancellation requires confirmation from your client, in which case the response will be the `invoice` object with the properties `status: "valid"` and `cancellation_status: "pending"`. + - The call is successful, but the SAT replies that the request was received and is being validated, in which case the response will be `status: "valid"` and `cancellation_status: "verifying"`. + + In the `pending` or `verifying` scenarios, the value of `cancellation_status` will be automatically updated by Facturapi when the SAT or your client accepts, rejects, or lets the request expire, so that when you query an invoice (using [Get Invoice](#tag/invoice/operation/getInvoice)), the `cancellation_status` property will reflect the most recent status of the request. + + Check the possible values of `cancellation_status` below. + + After the cancellation, the invoice will no longer be valid, the object will change its `status` to `"canceled"` and will still be available for future queries. + + If the status of the invoice is `draft`, this method will delete it from the database. + + If the status of the invoice is not `valid`, this method will return an error. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000 \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d?motive=02 \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X DELETE - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequest = await facturapi.invoices.retrieveZipRequest( - '66b0f0000000000000000000' + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.cancel( + '58e93bd8e86eb318b019743d', + { motive: '02' } ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequest = await facturapi.Invoice.RetrieveZipRequestAsync( - "66b0f0000000000000000000" + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.CancelAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["motive"] = "02" + } ); - lang: Java label: Java source: | import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequest = facturapi.invoices().retrieveZipRequest( - "66b0f0000000000000000000" - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().cancel( + "inv_123", + Map.of( + "motive", "02" + ) + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequest = $facturapi->Invoices->retrieveZipRequest( - "66b0f0000000000000000000" + $facturapi = new Facturapi("sk_test_API_KEY"); + $canceled_invoice = $facturapi->Invoices->cancel( + "58e93bd8e86eb318b019743d", + [ + "motive" => "02" + ] ); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID of the invoice to cancel + - in: query + name: motive + required: false + schema: + type: string + enum: + - '01' + - '02' + - '03' + - '04' + description: | + Required for issued documents; omit query parameters to delete a draft. + Key representing the motive for the cancellation of the invoice. + + Possible values: + + - `01`: **Invoice issued with errors with relation**. When the invoice contains any errors in quantities, keys, or any other data and the replacement invoice has already been issued, which should be indicated through the `substitution` attribute. + - `02`: **Invoice issued with errors without relation**. When the invoice contains any errors in quantities, keys, or any other data and it is not required to be related to another invoice. + - `03`: **Operation not carried out**. When the sale or transaction was not completed. + - `04`: **Nominative operation related to the global invoice**. When it is necessary to cancel an invoice to the general public because the customer requests their invoice. + - in: query + name: substitution + required: false + schema: + type: string + description: | + ID of the invoice that replaces the invoice being canceled. + + You can use either the ID assigned by Facturapi or the fiscal folio (UUID). + Required for motives 01 and 04. Draft deletion does not require query parameters. security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: ZIP request retrieved successfully. + description: "`Invoice` object after cancellation" content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequest" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}/zip: - get: - operationId: downloadInvoiceZipRequest + /invoices/{invoice_id}/copy: + post: + operationId: copyToDraftInvoice tags: - invoice - summary: Download a monthly ZIP + summary: Copy to draft description: | - Downloads the ZIP for a finished request. The filename uses the `YYYY-MM.zip` format. - - Requires a live-mode organization API key, an active subscription, and permission to read invoices. + Creates a new draft invoice with the same information as the specified invoice. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/zip \ - -H "Authorization: Bearer sk_live_API_KEY" \ - --output 2025-03.zip + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/copy \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST - lang: JavaScript label: Node.js source: | - import fs from 'fs'; - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipStream = await facturapi.invoices.downloadZipRequest( - '66b0f0000000000000000000' - ); - zipStream.pipe(fs.createWriteStream('./2025-03.zip')); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.copyToDraft('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipStream = await facturapi.Invoice.DownloadZipRequestAsync( - "66b0f0000000000000000000" - ); - await using var file = File.Create("2025-03.zip"); - await zipStream.CopyToAsync(file); + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.CopyToDraftAsync("58e93bd8e86eb318b019743d"); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.io.InputStream; - import java.nio.file.Files; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; + import java.util.List; + import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - try (InputStream zipStream = facturapi.invoices().downloadZipRequest( - "66b0f0000000000000000000" - )) { - Files.copy(zipStream, Path.of("./2025-03.zip"), StandardCopyOption.REPLACE_EXISTING); - } + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var draft = facturapi.invoices().copyToDraft( + "inv_123" + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zip = $facturapi->Invoices->downloadZipRequest( - "66b0f0000000000000000000" - ); - file_put_contents("2025-03.zip", $zip); + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->copyToDraft("58e93bd8e86eb318b019743d"); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID of the invoice to copy security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Generated ZIP file. - headers: - Content-Disposition: - description: Suggested filename in `attachment; filename="YYYY-MM.zip"` format. - schema: - type: string + description: "`Invoice` draft object created successfully" content: - application/zip: + application/json: schema: - type: string - format: binary + $ref: "#/components/schemas/InvoiceDraft" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" - "409": - $ref: "#/components/responses/InvoiceZipRequestNotReady" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}/download-url: - get: - operationId: getInvoiceZipRequestDownloadUrl + /invoices/{invoice_id}/stamp: + post: + operationId: stampDraftInvoice tags: - invoice - summary: Get monthly ZIP download URL + summary: Stamp draft invoice description: | - Returns a temporary URL for downloading the ZIP of a finished request without the file travelling through your server. + Stamps a draft invoice and sends it to the SAT for validation. - The URL grants access to that one file while it is valid: treat it as a credential and do not store it. Requires a live-mode organization API key, an active subscription, and permission to read invoices. + When using this method, the value of the `is_ready_to_stamp` field (assigned by Facturapi) + must be `true`. Otherwise, the call will return an error. To get the value of `is_ready_to_stamp`, + use the [Get Invoice](#tag/invoice/operation/getInvoice) method. + + This method does not allow editing the invoice, only stamping it. If you need to edit + information in the invoice before stamping it, use the [Edit Draft Invoice](#tag/invoice/operation/editDraftInvoice) method. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/download-url \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/stamp \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const stampedInvoice = await facturapi.invoices.stampDraft('58e93bd8e86eb318b019743d'); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var stampedInvoice = await facturapi.Invoice.StampDraftAsync("58e93bd8e86eb318b019743d"); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - const facturapi = new Facturapi('sk_live_API_KEY'); - const download = await facturapi.invoices.downloadZipRequestUrl( - '66b0f0000000000000000000' - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - console.log(download.url, download.expires_at); + var invoice = facturapi.invoices().stampDraft( + "inv_123", + Map.of( + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + $stamped_invoice = $facturapi->Invoices->stampDraft("58e93bd8e86eb318b019743d"); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID of the invoice to stamp + - in: query + name: async + schema: + type: boolean + required: false + description: | + Useful for large invoices. If sent `false` or not sent, the call will wait for the SAT to respond by stamping the invoice. + If sent `true`, the call will return immediately with the `invoice` object in status `pending`, and its status can be checked + for a change to `valid` at a later time. security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the generated ZIP file. + description: "`Invoice` object stamped successfully" content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" "409": - $ref: "#/components/responses/InvoiceZipRequestNotReady" + $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/preview/pdf: - post: - operationId: previewInvoicePdf + + /invoices/{invoice_id}/status: + put: + operationId: updateInvoiceStatus tags: - invoice - summary: Preview invoice PDF + summary: | + Update invoice status description: | - Generates a PDF preview of an invoice **without stamping it**. The PDF will be generated with the default template of your organization. + Consults the status of a stamped invoice at the SAT and updates the invoice object with the most recent information. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/preview/pdf \ + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/status \ -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "customer": { - "legal_name": "Dunder Mifflin", - "email": "email@example.com", - "tax_id": "ABC101010111", - "tax_system": "601", - "address": { - "zip": "85900" - } - }, - "items": [{ - "quantity": 2, - "product": { - "description": "Ukelele", - "product_key": "60131324", - "price": 345.60 - } - }], - "payment_form": "06", - "folio_number": 914, - "series": "F" - }' + -X PUT - lang: JavaScript label: Node.js source: | - const Facturapi = require('facturapi'); - - const facturapi = new Facturapi('sk_live_API_KEY'); - const pdfStream = await facturapi.invoices.previewPdf({ - customer: { - legal_name: 'Dunder Mifflin', - email: 'email@example.com', - tax_id: 'ABC101010111', - tax_system: '601', - address: { - zip: '85900' - } - }, - items: [{ - quantity: 2, - product: { - description: 'Ukelele', - product_key: '60131324', - price: 345.60 - } - }], - payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO, - folio_number: 914, - series: 'F' - }); - // Save the PDF to a file - const fs = require('fs'); - const file = fs.createWriteStream('/route/to/save/invoice.pdf'); - pdfStream.pipe(file); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.updateStatus('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var pdfStream = await facturapi.Invoice.PreviewPdfAsync(new Dictionary - { - ["customer"] = new Dictionary - { - ["legal_name"] = "Dunder Mifflin", - ["email"] = "email@example.com", - ["tax_id"] = "ABC101010111", - ["tax_system"] = "601", - ["address"] = new Dictionary - { - ["zip"] = "85900" - } - }, - ["items"] = new Dictionary[] - { - new Dictionary - { - ["product"] = new Dictionary - { - ["description"] = "Ukelele", - ["product_key"] = "60131324", - ["price"] = 345.60 - } - } - }, - ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO, - ["folio_number"] = 914, - ["series"] = "F" - }); - // Save the PDF to a file - var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.pdf", FileMode.Create); - pdfStream.CopyTo(file); - file.Close(); + var facturapi = new Facturapi + var invoice = await facturapi.Invoice.UpdateStatusAsync("58e93bd8e86eb318b019743d"); - lang: Java label: Java source: | @@ -4108,94 +4133,30 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var pdf = facturapi.invoices().previewPdf( - Map.of( - "customer", "cus_123", - "items", List.of( - Map.of( - "quantity", 1, - "product", "prod_123" - ) - ) - )); + var invoice = facturapi.invoices().updateStatus( + "inv_123" + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $pdfContent = $facturapi->Invoices->previewPdf([ - "customer" => [ - "legal_name" => "Dunder Mifflin", - "email" => "email@example.com", - "tax_id" => "ABC101010111", - "tax_system" => "601", - "address" => [ - "zip" => "85900" - ] - ], - "items" => [ - [ - "quantity" => 2, - "product" => [ - "description" => "Ukelele", - "product_key" => "60131324", - "price" => 345.60, - "sku" => "ABC4567" - ] - ] - ], - "payment_form" => \Facturapi\PaymentForm::EFECTIVO, - "folio_number" => 914, - "series" => "F" - ]); - requestBody: - $ref: "#/components/requestBodies/InvoiceCreate" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: PDF binary content - content: - application/pdf: - schema: - type: string - format: binary - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /invoices/preview/pdf/download-url: - post: - operationId: previewInvoicePdfUrl - tags: - - invoice - summary: Get invoice PDF preview URL - description: Returns a temporary URL for an unstamped invoice PDF preview. - x-codeSamples: - - lang: JavaScript - label: Node.js - source: | - const download = await facturapi.invoices.previewPdfUrl({ - customer: 'cus_123', - items: [{ product: 'prod_123' }], - payment_form: '06' - }); - console.log(download.url, download.expires_at); - requestBody: - $ref: "#/components/requestBodies/InvoiceCreate" + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->updateStatus("58e93bd8e86eb318b019743d"); + parameters: + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID of the invoice to update security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the PDF preview. + description: "`Invoice` object updated successfully" content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": @@ -4204,117 +4165,285 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}: + + /invoices/{invoice_id}/payment-summary: get: - operationId: getInvoice + operationId: getInvoicePaymentSummary tags: - invoice - summary: Retrieve invoice by ID - description: Returns the `Invoice` object with the specified ID. If the invoice does not exist, a 404 error will be returned. + summary: Payment summary + description: | + Returns 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 (`last_balance`), and the invoice tax breakdown prorated to the amount + being paid. + + The response is ready to be used as an element of `related_documents` when + [creating a Payment invoice](#tag/invoice/operation/createInvoice). + + The `amount` parameter must be expressed in the invoice currency and cannot exceed the + outstanding balance (`amount_due`). When the payment is received in a different currency, + convert the amount before calling this method. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + curl "https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/payment-summary?amount=100" \ -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.retrieve('58e93bd8e86eb318b019743d'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.RetrieveAsync("58e93bd8e86eb318b019743d"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + const summary = await facturapi.invoices.paymentSummary( + '58e93bd8e86eb318b019743d', + { amount: 100 } + ); - var invoice = facturapi.invoices().retrieve( - "inv_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->retrieve( "58e93bd8e86eb318b019743d" ); + // The summary goes as-is into the complement's related documents + const invoice = await facturapi.invoices.create({ + type: 'P', + customer: 'customer_id', + complements: [ + { + type: 'pago', + data: [ + { + payment_form: '28', + related_documents: [summary] + } + ] + } + ] + }); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID of the invoice + description: ID of the income invoice (PPD payment method) being paid + - in: query + name: amount + schema: + type: number + required: true + description: Amount being paid on this invoice, expressed in the invoice currency. Cannot exceed the outstanding balance. security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: "`Invoice` object" + description: Related document summary content: application/json: schema: - $ref: "#/components/schemas/Invoice" + type: object + required: + - uuid + - series + - installment + - last_balance + - total + - currency + - amount + - taxes + properties: + uuid: + type: string + description: Invoice UUID + folio_number: + type: number + description: Invoice folio number. Omitted when the invoice has none registered. + series: + type: ["string","null"] + description: Invoice series + installment: + type: number + description: Installment number corresponding to this payment + last_balance: + type: number + description: Invoice outstanding balance before this payment + total: + type: number + description: Invoice total + currency: + type: string + description: Invoice currency + amount: + type: number + description: Amount paid in this installment + taxes: + type: array + description: Invoice taxes prorated to the paid amount + items: + type: object + required: + - base + - rate + - type + - factor + - withholding + properties: + base: + type: number + description: Tax base prorated to the paid amount + rate: + type: number + description: Tax rate or quota + type: + type: string + enum: + - IVA + - ISR + - IEPS + description: Tax type (VAT, income tax withholding, etc.) + factor: + type: string + enum: + - Tasa + - Cuota + - Exento + description: Factor type (Rate, Exempt, etc.) + withholding: + type: boolean + description: Whether this tax is a withholding + example: + uuid: 39c85a3f-275b-4341-b259-e8971d9f8a94 + folio_number: 914 + series: F + installment: 2 + last_balance: 245.6 + total: 345.6 + currency: MXN + amount: 100 + taxes: + - base: 86.21 + rate: 0.16 + type: IVA + factor: Tasa + withholding: false "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - put: - operationId: updateDraftInvoice + + /invoices/preview/pdf: + post: + operationId: previewInvoicePdf tags: - invoice - summary: Edit draft invoice + summary: Preview invoice PDF description: | - Updates the information of a draft invoice, setting only the values for - the paramenters that are sent. Undefined values will not be modified. - - In the `Invoice` response object, Facturapi will automatically assign the - `is_ready_to_stamp` field with the value `true` if the invoice passes the - minimum validation required to be stamped; otherwise, the - `is_ready_to_stamp` field will be `false`. + Generates a PDF preview of an invoice **without stamping it**. The PDF will be generated with the default template of your organization. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ - -X PUT \ + curl https://www.facturapi.io/v2/invoices/preview/pdf \ -H "Authorization: Bearer sk_test_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "payment_form": "06" - }' + "customer": { + "legal_name": "Dunder Mifflin", + "email": "email@example.com", + "tax_id": "ABC101010111", + "tax_system": "601", + "address": { + "zip": "85900" + } + }, + "items": [{ + "quantity": 2, + "product": { + "description": "Ukelele", + "product_key": "60131324", + "price": 345.60 + } + }], + "payment_form": "06", + "folio_number": 914, + "series": "F" + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.updateDraft( - '58e93bd8e86eb318b019743d', - { - payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO - } - ); - - lang: csharp + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const pdfStream = await facturapi.invoices.previewPdf({ + customer: { + legal_name: 'Dunder Mifflin', + email: 'email@example.com', + tax_id: 'ABC101010111', + tax_system: '601', + address: { + zip: '85900' + } + }, + items: [{ + quantity: 2, + product: { + description: 'Ukelele', + product_key: '60131324', + price: 345.60 + } + }], + payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO, + folio_number: 914, + series: 'F' + }); + // Save the PDF to a file + import fs from 'node:fs'; + const file = fs.createWriteStream('/route/to/save/invoice.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(file); + } + - lang: csharp label: C# source: | - var facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.UpdateDraftAsync( - "58e93bd8e86eb318b019743d", - new Dictionary + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var pdfStream = await facturapi.Invoice.PreviewPdfAsync(new Dictionary + { + ["customer"] = new Dictionary { - ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO - } - ); + ["legal_name"] = "Dunder Mifflin", + ["email"] = "email@example.com", + ["tax_id"] = "ABC101010111", + ["tax_system"] = "601", + ["address"] = new Dictionary + { + ["zip"] = "85900" + } + }, + ["items"] = new Dictionary[] + { + new Dictionary + { + ["product"] = new Dictionary + { + ["description"] = "Ukelele", + ["product_key"] = "60131324", + ["price"] = 345.60 + } + } + }, + ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO, + ["folio_number"] = 914, + ["series"] = "F" + }); + // Save the PDF to a file + var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.pdf", FileMode.Create); + pdfStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | @@ -4324,7 +4453,9 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = facturapi.invoices().updateDraft("inv_123", Map.of( + var pdf = facturapi.invoices().previewPdf( + Map.of( + "customer", "cus_123", "items", List.of( Map.of( "quantity", 1, @@ -4334,17 +4465,32 @@ paths: )); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->updateDraft("58e93bd8e86eb318b019743d", [ - "payment_form" => \Facturapi\PaymentForm::EFECTIVO + $facturapi = new Facturapi("sk_live_API_KEY"); + $pdfContent = $facturapi->Invoices->previewPdf([ + "customer" => [ + "legal_name" => "Dunder Mifflin", + "email" => "email@example.com", + "tax_id" => "ABC101010111", + "tax_system" => "601", + "address" => [ + "zip" => "85900" + ] + ], + "items" => [ + [ + "quantity" => 2, + "product" => [ + "description" => "Ukelele", + "product_key" => "60131324", + "price" => 345.60, + "sku" => "ABC4567" + ] + ] + ], + "payment_form" => \Facturapi\PaymentForm::EFECTIVO, + "folio_number" => 914, + "series" => "F" ]); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID of the invoice to edit requestBody: $ref: "#/components/requestBodies/InvoiceEdit" security: @@ -4352,11 +4498,12 @@ paths: - "SecretTestKey": [] responses: "200": - description: "`Invoice` object edited successfully" + description: PDF binary content content: - application/json: + application/pdf: schema: - $ref: "#/components/schemas/InvoiceDraft" + type: string + format: binary "400": $ref: "#/components/responses/BadRequest" "401": @@ -4365,195 +4512,169 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - delete: - operationId: cancelInvoice + /invoices/preview/pdf/download-url: + post: + operationId: previewInvoicePdfUrl tags: - invoice - summary: Cancel invoice - description: | - Creates a cancellation request to the SAT for the specified invoice, using the **SAT's new cancellation scheme (effective since 2022)**. - - When using this method, the following results can occur: - - - The call returns an error with the explanation of why the cancellation could not be completed. - - The call is successful and returns an `invoice` object with the property `status: "canceled"` (the cancellation has already been accepted by the SAT). - - The call is successful, but the cancellation requires confirmation from your client, in which case the response will be the `invoice` object with the properties `status: "valid"` and `cancellation_status: "pending"`. - - The call is successful, but the SAT replies that the request was received and is being validated, in which case the response will be `status: "valid"` and `cancellation_status: "verifying"`. - - In the `pending` or `verifying` scenarios, the value of `cancellation_status` will be automatically updated by Facturapi when the SAT or your client accepts, rejects, or lets the request expire, so that when you query an invoice (using [Get Invoice](#tag/invoice/operation/getInvoice)), the `cancellation_status` property will reflect the most recent status of the request. - - Check the possible values of `cancellation_status` below. - - After the cancellation, the invoice will no longer be valid, the object will change its `status` to `"canceled"` and will still be available for future queries. - - If the status of the invoice is `draft`, this method will delete it from the database. - - If the status of the invoice is not `valid`, this method will return an error. + summary: Get invoice PDF preview URL + description: Returns an object containing file metadata and a temporary URL for an unstamped invoice PDF preview. x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d?motive=02 \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X DELETE - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' + import Facturapi from 'facturapi'; const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.cancel( - '58e93bd8e86eb318b019743d', - { motive: '02' } - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.CancelAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["motive"] = "02" - } - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var invoice = facturapi.invoices().cancel( - "inv_123", - Map.of( - "motive", "02" - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $canceled_invoice = $facturapi->Invoices->cancel( - "58e93bd8e86eb318b019743d", - [ - "motive" => "02" - ] - ); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID of the invoice to cancel - - in: query - name: motive - required: true - schema: - type: string - enum: - - "01" - - "02" - - "03" - - "04" - description: | - Key representing the motive for the cancellation of the invoice. - - Possible values: - - `01`: **Invoice issued with errors with relation**. When the invoice contains any errors in quantities, keys, or any other data and the replacement invoice has already been issued, which should be indicated through the `substitution` attribute. - - `02`: **Invoice issued with errors without relation**. When the invoice contains any errors in quantities, keys, or any other data and it is not required to be related to another invoice. - - `03`: **Operation not carried out**. When the sale or transaction was not completed. - - `04`: **Nominative operation related to the global invoice**. When it is necessary to cancel an invoice to the general public because the customer requests their invoice. - - in: query - name: substitution - required: false - schema: - type: string - description: | - ID of the invoice that replaces the invoice being canceled. - - You can use either the ID assigned by Facturapi or the fiscal folio (UUID). + const download = await facturapi.invoices.previewPdfUrl({ + customer: 'cus_123', + items: [{ product: 'prod_123' }], + payment_form: '06' + }); + console.log(download.url, download.expires_at); + requestBody: + $ref: "#/components/requestBodies/InvoiceEdit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: "`Invoice` object after cancellation" + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "409": - $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/copy: - post: - operationId: copyToDraftInvoice + /invoices/{invoice_id}/{format}: + get: + operationId: downloadInvoice tags: - invoice - summary: Copy to draft - description: | - Creates a new draft invoice with the same information as the specified invoice. + summary: Download invoice + description: Download your invoice in PDF, XML, or both in a ZIP file. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/copy \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST + ## Download PDF and XML compressed in a ZIP file + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/zip \ + -H "Authorization: Bearer sk_test_API_KEY" + + ## Download only the PDF + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + + ## Download only the XML + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/xml \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | + import fs from 'fs'; import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.copyToDraft('58e93bd8e86eb318b019743d'); + + // Download PDF and XML compressed in a ZIP file + const zipStream = await facturapi.invoices.downloadZip('58e93bd8e86eb318b019743d'); + const zipFile = fs.createWriteStream('./factura.zip'); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(zipFile); + } + + // Download only the PDF + const pdfStream = await facturapi.invoices.downloadPdf('58e93bd8e86eb318b019743d'); + const pdfFile = fs.createWriteStream('./factura.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } + + // Download only the XML + const xmlStream = await facturapi.invoices.downloadXml('58e93bd8e86eb318b019743d'); + const xmlFile = fs.createWriteStream('./factura.xml'); + if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(xmlFile); + } - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.CopyToDraftAsync("58e93bd8e86eb318b019743d"); + // Download PDF and XML compressed in a ZIP file + var zipStream = await facturapi.Invoice.DownloadZipAsync("58e93bd8e86eb318b019743d"); + // Download only the XML + var xmlStream = await facturapi.Invoice.DownloadXmlAsync("58e93bd8e86eb318b019743d"); + // Download only the PDF + var pdfStream = await facturapi.Invoice.DownloadPdfAsync("58e93bd8e86eb318b019743d"); + + // Save the streams to a file + var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.zip", FileMode.Create); + zipStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; + import java.io.InputStream; + import java.nio.file.Files; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var draft = facturapi.invoices().copyToDraft( - "inv_123" - ); + try (InputStream zipStream = facturapi.invoices().downloadZip("58e93bd8e86eb318b019743d")) { + Files.copy(zipStream, Path.of("./factura.zip"), StandardCopyOption.REPLACE_EXISTING); + } + + try (InputStream pdfStream = facturapi.invoices().downloadPdf("58e93bd8e86eb318b019743d")) { + Files.copy(pdfStream, Path.of("./factura.pdf"), StandardCopyOption.REPLACE_EXISTING); + } + + try (InputStream xmlStream = facturapi.invoices().downloadXml("58e93bd8e86eb318b019743d")) { + Files.copy(xmlStream, Path.of("./factura.xml"), StandardCopyOption.REPLACE_EXISTING); + } - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->copyToDraft("58e93bd8e86eb318b019743d"); + + // Stream containing the ZIP file with the PDF and XML files + $zip = $facturapi->Invoices->downloadZip("58e93bd8e86eb318b019743d"); + // Stream containing the PDF file + $pdf = $facturapi->Invoices->downloadPdf("58e93bd8e86eb318b019743d"); + // Stream containing the XML file + $xml = $facturapi->Invoices->downloadXml("58e93bd8e86eb318b019743d"); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID of the invoice to copy + description: ID of the invoice to download + - in: path + name: format + schema: + type: string + enum: + - xml + - pdf + - zip + required: true + description: Format of the file to download security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: "`Invoice` draft object created successfully" + description: Official CFDI file in the specified format content: - application/json: + application/octet-stream: schema: - $ref: "#/components/schemas/InvoiceDraft" + type: string + format: binary "400": $ref: "#/components/responses/BadRequest" "401": @@ -4562,94 +4683,72 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/stamp: - post: - operationId: stampDraftInvoice + /invoices/{invoice_id}/download-url/{format}: + get: + operationId: getInvoiceDownloadUrl tags: - invoice - summary: Stamp draft invoice + summary: Get download URL description: | - Stamps a draft invoice and sends it to the SAT for validation. - - When using this method, the value of the `is_ready_to_stamp` field (assigned by Facturapi) - must be `true`. Otherwise, the call will return an error. To get the value of `is_ready_to_stamp`, - use the [Get Invoice](#tag/invoice/operation/getInvoice) method. + Returns an object containing file metadata and a temporary URL to download the invoice in PDF, XML, or both in a ZIP file, without the file travelling through your server. - This method does not allow editing the invoice, only stamping it. If you need to edit - information in the invoice before stamping it, use the [Edit Draft Invoice](#tag/invoice/operation/editDraftInvoice) method. + The URL grants access to that one file while it is valid: treat it as a credential and do not store it. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/stamp \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const stampedInvoice = await facturapi.invoices.stampDraft('58e93bd8e86eb318b019743d'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var stampedInvoice = await facturapi.Invoice.StampDraftAsync("58e93bd8e86eb318b019743d"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; + import Facturapi from 'facturapi'; - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.invoices.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); - var invoice = facturapi.invoices().stampDraft( - "inv_123", - Map.of( - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $stamped_invoice = $facturapi->Invoices->stampDraft("58e93bd8e86eb318b019743d"); + console.log(download.url, download.expires_at); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID of the invoice to stamp - - in: query - name: async + description: ID of the object to download + - in: path + name: format schema: - type: boolean - required: false - description: | - Useful for large invoices. If sent `false` or not sent, the call will wait for the SAT to respond by stamping the invoice. - If sent `true`, the call will return immediately with the `invoice` object in status `pending`, and its status can be checked - for a change to `valid` at a later time. + type: string + enum: + - pdf + - xml + - zip + required: true + description: Format of the file to download security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: "`Invoice` object stamped successfully" + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "409": $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/cancellation_receipt/{format}: get: operationId: downloadCancellationReceiptXml @@ -4665,7 +4764,7 @@ paths: curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/xml \ -H "Authorization: Bearer sk_test_API_KEY" \ -X GET - + # Cancellation receipt pdf curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/pdf \ -H "Authorization: Bearer sk_test_API_KEY" \ @@ -4709,7 +4808,7 @@ paths: // Cancellation receipt xml $facturapi->Invoices->downloadCancellationReceiptXml("58e93bd8e86eb318b019743d"); - + // Cancellation receipt pdf $facturapi->Invoices->downloadCancellationReceiptPdf("58e93bd8e86eb318b019743d"); parameters: @@ -4748,143 +4847,59 @@ paths: "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/payment-summary: + /invoices/{invoice_id}/cancellation_receipt/download-url/{format}: get: - operationId: getInvoicePaymentSummary + operationId: getCancellationReceiptDownloadUrl tags: - invoice - summary: Payment summary + summary: Get cancellation receipt download URL description: | - Returns 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 (`last_balance`), and the invoice tax breakdown prorated to the amount - being paid. - - The response is ready to be used as an element of `related_documents` when - [creating a Payment invoice](#tag/invoice/operation/createInvoice). + Returns an object containing file metadata and a temporary URL to download the XML or PDF receipt issued by SAT when a cancellation request is submitted through Facturapi, without the file travelling through your server. The receipt contains the immediate request result and does not necessarily prove that the CFDI is already canceled; check the invoice status to confirm the outcome. - The `amount` parameter must be expressed in the invoice currency and cannot exceed the - outstanding balance (`amount_due`). When the payment is received in a different currency, - convert the amount before calling this method. + The URL grants access to that one file while it is valid: treat it as a credential and do not store it. x-codeSamples: - lang: Bash label: cURL source: | - curl "https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/payment-summary?amount=100" \ + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/download-url/pdf \ -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); + import Facturapi from 'facturapi'; - const summary = await facturapi.invoices.paymentSummary( - '58e93bd8e86eb318b019743d', - { amount: 100 } + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.invoices.downloadCancellationReceiptPdfUrl( + '58e93bd8e86eb318b019743d' ); - // The summary goes as-is into the complement's related documents - const invoice = await facturapi.invoices.create({ - type: 'P', - customer: 'customer_id', - complements: [ - { - type: 'pago', - data: [ - { - payment_form: '28', - related_documents: [summary] - } - ] - } - ] - }); + console.log(download.url, download.expires_at); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID of the income invoice (PPD payment method) being paid - - in: query - name: amount + description: ID of the object to download + - in: path + name: format schema: - type: number + type: string + enum: + - xml + - pdf required: true - description: Amount being paid on this invoice, expressed in the invoice currency. Cannot exceed the outstanding balance. + description: Format of the cancellation receipt security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Related document summary + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. content: application/json: schema: - type: object - properties: - uuid: - type: string - description: Invoice UUID - folio_number: - type: number - description: Invoice folio number. Omitted when the invoice has none registered. - series: - type: string - nullable: true - description: Invoice series - installment: - type: number - description: Installment number corresponding to this payment - last_balance: - type: number - description: Invoice outstanding balance before this payment - total: - type: number - description: Invoice total - currency: - type: string - description: Invoice currency - amount: - type: number - description: Amount paid in this installment - taxes: - type: array - description: Invoice taxes prorated to the paid amount - items: - type: object - properties: - base: - type: number - description: Tax base prorated to the paid amount - rate: - type: number - description: Tax rate or quota - type: - type: string - description: Tax type (VAT, income tax withholding, etc.) - factor: - type: string - description: Factor type (Rate, Exempt, etc.) - withholding: - type: boolean - description: Whether this tax is a withholding - example: - uuid: 39c85a3f-275b-4341-b259-e8971d9f8a94 - folio_number: 914 - series: F - installment: 2 - last_balance: 245.6 - total: 345.6 - currency: MXN - amount: 100 - taxes: - - base: 86.21 - rate: 0.16 - type: IVA - factor: Tasa - withholding: false + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": @@ -4895,132 +4910,6 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - - /invoices/{invoice_id}/{format}: - get: - operationId: downloadInvoice - tags: - - invoice - summary: Download invoice - description: Download your invoice in PDF, XML, or both in a ZIP file. - x-codeSamples: - - lang: Bash - label: cURL - source: | - ## Download PDF and XML compressed in a ZIP file - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/zip \ - -H "Authorization: Bearer sk_test_API_KEY" - - ## Download only the PDF - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" - - ## Download only the XML - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/xml \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import fs from 'fs'; - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - // Download PDF and XML compressed in a ZIP file - const zipStream = await facturapi.invoices.downloadZip('58e93bd8e86eb318b019743d'); - const zipFile = fs.createWriteStream('./factura.zip'); - zipStream.pipe(zipFile); - - // Download only the PDF - const pdfStream = await facturapi.invoices.downloadPdf('58e93bd8e86eb318b019743d'); - const pdfFile = fs.createWriteStream('./factura.pdf'); - pdfStream.pipe(pdfFile); - - // Download only the XML - const xmlStream = await facturapi.invoices.downloadXml('58e93bd8e86eb318b019743d'); - const xmlFile = fs.createWriteStream('./factura.xml'); - xmlStream.pipe(xmlFile); - - lang: csharp - label: C# - source: | - // Download PDF and XML compressed in a ZIP file - var zipStream = await facturapi.Invoice.DownloadZipAsync("58e93bd8e86eb318b019743d"); - // Download only the XML - var xmlStream = await facturapi.Invoice.DownloadXmlAsync("58e93bd8e86eb318b019743d"); - // Download only the PDF - var pdfStream = await facturapi.Invoice.DownloadPdfAsync("58e93bd8e86eb318b019743d"); - - // Save the streams to a file - var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.zip", FileMode.Create); - zipStream.CopyTo(file); - file.Close(); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.io.InputStream; - import java.nio.file.Files; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - try (InputStream zipStream = facturapi.invoices().downloadZip("58e93bd8e86eb318b019743d")) { - Files.copy(zipStream, Path.of("./factura.zip"), StandardCopyOption.REPLACE_EXISTING); - } - - try (InputStream pdfStream = facturapi.invoices().downloadPdf("58e93bd8e86eb318b019743d")) { - Files.copy(pdfStream, Path.of("./factura.pdf"), StandardCopyOption.REPLACE_EXISTING); - } - - try (InputStream xmlStream = facturapi.invoices().downloadXml("58e93bd8e86eb318b019743d")) { - Files.copy(xmlStream, Path.of("./factura.xml"), StandardCopyOption.REPLACE_EXISTING); - } - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // Stream containing the ZIP file with the PDF and XML files - $zip = $facturapi->Invoices->downloadZip("58e93bd8e86eb318b019743d"); - // Stream containing the PDF file - $pdf = $facturapi->Invoices->downloadPdf("58e93bd8e86eb318b019743d"); - // Stream containing the XML file - $xml = $facturapi->Invoices->downloadXml("58e93bd8e86eb318b019743d"); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID of the invoice to download - - in: path - name: format - schema: - type: string - enum: - - xml - - pdf - - zip - required: true - description: Format of the file to download - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Official CFDI file in the specified format - content: - application/octet-stream: - schema: - type: string - format: binary - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" /invoices/{invoice_id}/email: post: operationId: sendInvoiceByEmail @@ -5189,33 +5078,58 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/status: - put: - operationId: updateInvoiceStatus + /invoices/zip-requests: + post: + operationId: createInvoiceZipRequest tags: - invoice - summary: | - Update invoice status + summary: Create or retrieve a monthly ZIP request description: | - Consults the status of a stamped invoice at the SAT and updates the invoice object with the most recent information. + Creates a request to generate a ZIP file containing one month of invoices, or retrieves the existing request with the same filters. + + This operation is idempotent. Invoice types are normalized, so `["I", "E"]` and `["E", "I"]` resolve to the same request. Identical concurrent calls also return the same request. + + If an earlier request has a `failed` status, calling this method again retries it. Before retrying, the previous error and task fields, processed progress, and failed-document list are cleared. If scheduling fails, the request is saved with a `failed` status and the API returns a `5xx` error. + + This method requires a live-mode organization API key, an active subscription, and permission to read invoices. Test-mode keys return HTTP 402. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/status \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X PUT + curl https://www.facturapi.io/v2/invoices/zip-requests \ + -H "Authorization: Bearer sk_live_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "year": 2025, + "month": 3, + "issuer_type": "issuing", + "invoice_types": ["I", "E"] + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.updateStatus('58e93bd8e86eb318b019743d'); + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequest = await facturapi.invoices.createZipRequest({ + year: 2025, + month: 3, + issuer_type: 'issuing', + invoice_types: ['I', 'E'] + }); - lang: csharp label: C# source: | - var facturapi = new Facturapi - var invoice = await facturapi.Invoice.UpdateStatusAsync("58e93bd8e86eb318b019743d"); + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequest = await facturapi.Invoice.CreateZipRequestAsync( + new Dictionary + { + ["year"] = 2025, + ["month"] = 3, + ["issuer_type"] = "issuing", + ["invoice_types"] = new[] { "I", "E" } + } + ); - lang: Java label: Java source: | @@ -5223,41 +5137,393 @@ paths: import java.util.List; import java.util.Map; - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var invoice = facturapi.invoices().updateStatus( - "inv_123" - ); + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequest = facturapi.invoices().createZipRequest( + Map.of( + "year", 2025, + "month", 3, + "issuer_type", "issuing", + "invoice_types", List.of("I", "E") + ) + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->updateStatus("58e93bd8e86eb318b019743d"); + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequest = $facturapi->Invoices->createZipRequest([ + "year" => 2025, + "month" => 3, + "issuer_type" => "issuing", + "invoice_types" => ["I", "E"] + ]); + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequestCreateInput" + security: + - "SecretLiveKey": [] + responses: + "200": + description: ZIP request created or retrieved successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequest" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNoInvoices" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + get: + operationId: listInvoiceZipRequests + tags: + - invoice + summary: List monthly ZIP requests + description: | + Returns a paginated list of ZIP requests. `year` and `month` must be provided together. `invoice_types` filters by one type or an exact normalized array. + + This method requires a live-mode organization API key, an active subscription, and permission to read invoices. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl "https://www.facturapi.io/v2/invoices/zip-requests?year=2025&month=3&status=finished&limit=20&page=1" \ + -H "Authorization: Bearer sk_live_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequests = await facturapi.invoices.listZipRequests({ + year: 2025, + month: 3, + status: 'finished', + limit: 20, + page: 1 + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequests = await facturapi.Invoice.ListZipRequestsAsync( + new Dictionary + { + ["year"] = 2025, + ["month"] = 3, + ["status"] = "finished", + ["limit"] = 20, + ["page"] = 1 + } + ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequests = facturapi.invoices().listZipRequests( + Map.of( + "year", 2025, + "month", 3, + "status", "finished", + "limit", 20, + "page", 1 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequests = $facturapi->Invoices->listZipRequests([ + "year" => 2025, + "month" => 3, + "status" => "finished", + "limit" => 20, + "page" => 1 + ]); + parameters: + - in: query + name: year + schema: + type: integer + minimum: 2000 + maximum: 9999 + description: Year to filter. Must be provided with `month`. + - in: query + name: month + schema: + type: integer + minimum: 1 + maximum: 12 + description: Month to filter. Must be provided with `year`. + - in: query + name: status + schema: + $ref: "#/components/schemas/InvoiceZipRequestStatus" + description: ZIP request status. + - in: query + name: issuer_type + schema: + $ref: "#/components/schemas/IssuingType" + description: Filters issued or received invoices. + - in: query + name: invoice_types + schema: + type: array + uniqueItems: true + items: + $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" + description: Filters by one invoice type or an exact normalized array. + - in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: Results page, starting at 1. + - $ref: "#/components/parameters/SearchLimit" + security: + - "SecretLiveKey": [] + responses: + "200": + description: Paginated ZIP request results. + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequestSearchResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /invoices/zip-requests/{id}: + get: + operationId: retrieveInvoiceZipRequest + tags: + - invoice + summary: Retrieve a monthly ZIP request + description: | + Retrieves a ZIP request. Poll this method until the status becomes `finished` or `failed`. Once it is `finished`, call the download method. + + Requires a live-mode organization API key, an active subscription, and permission to read invoices. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000 \ + -H "Authorization: Bearer sk_live_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequest = await facturapi.invoices.retrieveZipRequest( + '66b0f0000000000000000000' + ); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequest = await facturapi.Invoice.RetrieveZipRequestAsync( + "66b0f0000000000000000000" + ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequest = facturapi.invoices().retrieveZipRequest( + "66b0f0000000000000000000" + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequest = $facturapi->Invoices->retrieveZipRequest( + "66b0f0000000000000000000" + ); + parameters: + - $ref: "#/components/parameters/InvoiceZipRequestId" + security: + - "SecretLiveKey": [] + responses: + "200": + description: ZIP request retrieved successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequest" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /invoices/zip-requests/{id}/zip: + get: + operationId: downloadInvoiceZipRequest + tags: + - invoice + summary: Download a monthly ZIP + description: | + Downloads the ZIP for a finished request. The filename uses the `YYYY-MM.zip` format. + + Requires a live-mode organization API key, an active subscription, and permission to read invoices. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/zip \ + -H "Authorization: Bearer sk_live_API_KEY" \ + --output 2025-03.zip + - lang: JavaScript + label: Node.js + source: | + import fs from 'fs'; + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipStream = await facturapi.invoices.downloadZipRequest( + '66b0f0000000000000000000' + ); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(fs.createWriteStream('./2025-03.zip')); + } + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipStream = await facturapi.Invoice.DownloadZipRequestAsync( + "66b0f0000000000000000000" + ); + await using var file = File.Create("2025-03.zip"); + await zipStream.CopyToAsync(file); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.io.InputStream; + import java.nio.file.Files; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + try (InputStream zipStream = facturapi.invoices().downloadZipRequest( + "66b0f0000000000000000000" + )) { + Files.copy(zipStream, Path.of("./2025-03.zip"), StandardCopyOption.REPLACE_EXISTING); + } + - lang: PHP + source: | + $facturapi = new Facturapi("sk_live_API_KEY"); + $zip = $facturapi->Invoices->downloadZipRequest( + "66b0f0000000000000000000" + ); + file_put_contents("2025-03.zip", $zip); + parameters: + - $ref: "#/components/parameters/InvoiceZipRequestId" + security: + - "SecretLiveKey": [] + responses: + "200": + description: Generated ZIP file. + headers: + Content-Disposition: + description: Suggested filename in `attachment; filename="YYYY-MM.zip"` format. + schema: + type: string + content: + application/zip: + schema: + type: string + format: binary + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/InvoiceZipRequestNotReady" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /invoices/zip-requests/{id}/download-url: + get: + operationId: getInvoiceZipRequestDownloadUrl + tags: + - invoice + summary: Get monthly ZIP download URL + description: | + Returns an object containing file metadata and a temporary URL for downloading the ZIP of a finished request without the file travelling through your server. + + The URL grants access to that one file while it is valid: treat it as a credential and do not store it. Requires a live-mode organization API key, an active subscription, and permission to read invoices. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/download-url \ + -H "Authorization: Bearer sk_live_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const download = await facturapi.invoices.downloadZipRequestUrl( + '66b0f0000000000000000000' + ); + + console.log(download.url, download.expires_at); parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID of the invoice to update + - $ref: "#/components/parameters/InvoiceZipRequestId" security: - "SecretLiveKey": [] - - "SecretTestKey": [] responses: "200": - description: "`Invoice` object updated successfully" + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/InvoiceZipRequestNotReady" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts: post: operationId: createReceipt @@ -5266,7 +5532,7 @@ paths: summary: Create e-receipt description: | Creates a new e-Receipt, which acts as a sales note. - + Every receipt will have an auto-generated URL that the client can visit to fill in their fiscal data in a microsite with the organization's branding. x-codeSamples: - lang: Bash @@ -5414,11 +5680,11 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // All receipts of the organization - const receiptSearch = await facturapi.receipts.list(); + const receiptSearch1 = await facturapi.receipts.list(); // Page 3 of search results for free text search // of receipts created between 2017 and 2019 - const receiptSearch = await facturapi.receipts.list({ + const receiptSearch2 = await facturapi.receipts.list({ q: 'Aspiradora Robot', date: { gte: new Date('2017-01-01T00:00:00.000Z'), @@ -5649,13 +5915,13 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // Assign an existing customer by ID - const receipt = await facturapi.receipts.assignCustomer( + const receipt = await facturapi.receipts.updateCustomer( '58e93bd8e86eb318b019743d', { customer: '58e93bd8e86eb318b0197456' } ); // Or create the customer from payload and assign it to the receipt - const receiptWithNewCustomer = await facturapi.receipts.assignCustomer( + const receiptWithNewCustomer = await facturapi.receipts.updateCustomer( '58e93bd8e86eb318b019743d', { customer: { @@ -5767,7 +6033,7 @@ paths: summary: Cancel e-receipt description: | Cancel a receipt by changing its `status` property to `"canceled"`. - + Once canceled, the receipt cannot be invoiced. x-codeSamples: - lang: Bash @@ -5803,258 +6069,23 @@ paths: source: | $facturapi = new Facturapi("sk_test_API_KEY"); $facturapi->Receipts->cancel("5ebd8e56f5687a013ca0df46"); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID of the receipt to cancel - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Receipt object canceled successfully - content: - application/json: - schema: - $ref: "#/components/schemas/Receipt" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/pdf: - get: - operationId: downloadReceiptPdf - tags: - - receipt - summary: Download PDF - description: Download the electronic receipt in PDF format. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import fs from 'fs'; - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - // Download the electronic receipt in PDF format - const pdfStream = await facturapi.receipts.downloadPdf('58e93bd8e86eb318b019743d'); - const pdfFile = fs.createWriteStream('./recibo.pdf'); - pdfStream.pipe(pdfFile); - - lang: csharp - label: C# - source: | - // Download the electronic receipt in PDF format - var pdfStream = await facturapi.Receipt.DownloadPdfAsync("58e93bd8e86eb318b019743d"); - - // Save the stream to a file - var file = new System.IO.FileStream("C:\\route\\to\\save\\receipt.pdf", FileMode.Create); - pdfStream.CopyTo(file); - file.Close(); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - byte[] pdf = facturapi.receipts().downloadPdf( - "rec_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // stream containing the PDF file - $pdf = $facturapi->Receipts->downloadPdf("58e93bd8e86eb318b019743d"); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID of the receipt to download - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: E-receipt in PDF format - content: - application/octet-stream: - schema: - type: string - format: binary - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/email: - post: - operationId: sendReceiptByEmail - tags: - - receipt - summary: Send e-receipt by email - description: | - Send the e-receipt by email to the customer. - - The email sent will be customized with the logo and colors of the organization that created it, - and will include a button to invoice the receipt, as well as the receipt attached as a PDF to the message. - x-codeSamples: - - lang: Bash - label: cURL - source: | - # Send to a different email than the one registered by the customer - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/email \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST \ - -H "Content-Type: application/json" \ - -d '{ - "email": "another_email@example.com" - }' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - # Send to a different email than the one registered by the customer - await facturapi.receipts.sendByEmail( - '58e93bd8e86eb318b019743d', - { email: 'ejemplo@correo.com' } - ); - - # Send to multiple emails (max 10) - await facturapi.receipts.sendByEmail( - '58e93bd8e86eb318b019743d', - { - email: [ - 'primer@correo.com', - 'segundo@correo.com' - ] - } - ); - - lang: csharp - label: C# - source: | - // Send to a different email than the one registered by the customer - await facturapi.Receipt.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = "ejemplo@correo.com" - } - ); - - // Send to multiple emails (max 10) - await facturapi.Receipt.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = new String[] - { - "primer@correo.com", - "segundo@correo.com" - } - } - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var response = facturapi.receipts().sendByEmail( - "rec_123", - Map.of( - "to", "cliente@example.com" - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // Send to a different email than the one registered by the customer - $facturapi->Receipts->sendByEmail( - "58e93bd8e86eb318b019743d", - "ejemplo@correo.com" - ); - - // Send to multiple emails (max 10) - $facturapi->Receipts->sendByEmail( - "58e93bd8e86eb318b019743d", - [ - "primer@correo.com", - "segundo@correo.com" - ] - ); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID of the e-receipt to send - requestBody: - required: false - content: - application/json: - schema: - type: object - required: - - email - properties: - email: - description: | - Email address to send the e-receipt. If not sent, the email registered by the customer will be used. - oneOf: - - type: string - format: email - description: Email address to send the e-receipt. - example: other@email.com - - type: array - example: ["first@email.com", "second@email.com"] - description: | - Array of email addresses to send the e-receipt. The maximum number of emails is 10. - maxLength: 10 - items: - type: string - format: email + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID of the receipt to cancel security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Generic response object + description: Receipt object canceled successfully content: application/json: schema: - type: object - required: - - ok - properties: - ok: - type: boolean - description: Indicates if the email was sent successfully + $ref: "#/components/schemas/Receipt" "400": $ref: "#/components/responses/BadRequest" "401": @@ -6063,7 +6094,6 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/invoice: post: operationId: invoiceReceipt @@ -6338,43 +6368,295 @@ paths: label: Node.js source: | import Facturapi from 'facturapi' - import fs from 'fs' + import fs from 'fs' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const pdfStream = await facturapi.receipts.previewToInvoicePdf({ + keys: ['ticket_1001', 'ticket_1002'], + customer: { + legal_name: 'Dunder Mifflin', + tax_id: 'ABC101010111', + tax_system: '601', + address: { + zip: '85900' + } + }, + use: 'G03' + }); + + const file = fs.createWriteStream('to_invoice_preview.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(file); + } + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var pdfStream = await facturapi.Receipt.PreviewToInvoicePdfAsync(new Dictionary + { + ["keys"] = new[] { "ticket_1001", "ticket_1002" }, + ["customer"] = new Dictionary + { + ["legal_name"] = "Dunder Mifflin", + ["tax_id"] = "ABC101010111", + ["tax_system"] = "601", + ["address"] = new Dictionary + { + ["zip"] = "85900" + } + }, + ["use"] = "G03" + }); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var pdf = facturapi.receipts().previewToInvoicePdf( + Map.of( + "keys", List.of("ticket_1001", "ticket_1002"), + "customer", Map.of( + "legal_name", "Dunder Mifflin", + "tax_id", "ABC101010111", + "tax_system", "601", + "address", Map.of("zip", "85900") + ), + "use", "G03" + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $pdfBytes = $facturapi->Receipts->previewToInvoicePdf([ + "keys" => ["ticket_1001", "ticket_1002"], + "customer" => [ + "legal_name" => "Dunder Mifflin", + "tax_id" => "ABC101010111", + "tax_system" => "601", + "address" => [ + "zip" => "85900" + ] + ], + "use" => "G03" + ]); + requestBody: + $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: PDF binary content + content: + application/pdf: + schema: + type: string + format: binary + "204": + description: No eligible receipts found for the provided keys + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "500": + $ref: "#/components/responses/UnexpectedError" + /receipts/to-invoice/preview/download-url: + post: + operationId: previewToInvoiceFromReceiptsUrl + tags: + - receipt + summary: Get receipts invoice preview URL + description: Returns an object containing file metadata and a temporary URL for the PDF preview of an invoice built from the selected receipts. + x-codeSamples: + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + const facturapi = new Facturapi('sk_test_API_KEY'); + + const download = await facturapi.receipts.previewToInvoicePdfUrl({ + keys: ['ticket_1001', 'ticket_1002'], + customer: 'cus_123', + use: 'G03' + }); + console.log(download.url, download.expires_at); + requestBody: + $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. + content: + application/json: + schema: + $ref: "#/components/schemas/SignedDownloadUrl" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /receipts/global-invoice: + post: + operationId: createGlobalInvoice + tags: + - receipt + summary: Create global invoice + description: | + Creates a global invoice that will include all receipts with `status = "open"` from a certain period. + + Global invoices are issued to the generic `PUBLICO EN GENERAL` customer. + Included receipts are associated with that customer and their `status` + changes to `"invoiced_globally"`. + + A global invoice can include up to 5,000 open receipts. If the period contains + more, send `limit_to_max_receipts: true` and repeat the request with the same + period until the response is `null`. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/global-invoice \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "from": "2021-01-01T00:00:00.000Z", + "to": "2021-01-31T23:59:59.999Z", + "periodicity": "month", + "months": "01", + "folio_number": 1234, + "series": "G", + "limit_to_max_receipts": true + }' + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const invoice = await facturapi.receipts.createGlobalInvoice({ + from: '2021-01-01T00:00:00.000Z', + to: '2021-01-31T23:59:59.999Z', + periodicity: 'month', + months: '01', + folio_number: 1234, + series: 'G', + limit_to_max_receipts: true + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Receipt.CreateGlobalInvoiceAsync(new Dictionary + { + ["from"] = "2021-01-01T00:00:00.000Z", + ["to"] = "2021-01-31T23:59:59.999Z", + ["periodicity"] = "month", + ["months"] = "01", + ["folio_number"] = 1234, + ["series"] = "G" + }); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.receipts().createGlobalInvoice( + Map.of( + "from", "2021-01-01T00:00:00.000Z", + "to", "2021-01-31T23:59:59.999Z", + "periodicity", "month", + "months", "01" + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $invoice = $facturapi->Receipts->createGlobalInvoice([ + "from" => "2021-01-01T00:00:00.000Z", + "to" => "2021-01-31T23:59:59.999Z", + "periodicity" => "month", + "months" => "01", + "folio_number" => 1234, + "series" => "G" + ]); + requestBody: + $ref: "#/components/requestBodies/ReceiptCreateGlobalInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Created `Invoice` object, or `null` when the period has no open receipts + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/Invoice" + - type: "null" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + + /receipts/{receipt_id}/pdf: + get: + operationId: downloadReceiptPdf + tags: + - receipt + summary: Download PDF + description: Download the electronic receipt in PDF format. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import fs from 'fs'; + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const pdfStream = await facturapi.receipts.previewToInvoicePdf({ - keys: ['ticket_1001', 'ticket_1002'], - customer: { - legal_name: 'Dunder Mifflin', - tax_id: 'ABC101010111', - tax_system: '601', - address: { - zip: '85900' - } - }, - use: 'G03' - }); - - const file = fs.createWriteStream('to_invoice_preview.pdf'); - pdfStream.pipe(file); + // Download the electronic receipt in PDF format + const pdfStream = await facturapi.receipts.downloadPdf('58e93bd8e86eb318b019743d'); + const pdfFile = fs.createWriteStream('./recibo.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var pdfStream = await facturapi.Receipt.PreviewToInvoicePdfAsync(new Dictionary - { - ["keys"] = new[] { "ticket_1001", "ticket_1002" }, - ["customer"] = new Dictionary - { - ["legal_name"] = "Dunder Mifflin", - ["tax_id"] = "ABC101010111", - ["tax_system"] = "601", - ["address"] = new Dictionary - { - ["zip"] = "85900" - } - }, - ["use"] = "G03" - }); + // Download the electronic receipt in PDF format + var pdfStream = await facturapi.Receipt.DownloadPdfAsync("58e93bd8e86eb318b019743d"); + + // Save the stream to a file + var file = new System.IO.FileStream("C:\\route\\to\\save\\receipt.pdf", FileMode.Create); + pdfStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | @@ -6383,81 +6665,81 @@ paths: import java.util.Map; Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var pdf = facturapi.receipts().previewToInvoicePdf( - Map.of( - "keys", List.of("ticket_1001", "ticket_1002"), - "customer", Map.of( - "legal_name", "Dunder Mifflin", - "tax_id", "ABC101010111", - "tax_system", "601", - "address", Map.of("zip", "85900") - ), - "use", "G03" - ) - ); + byte[] pdf = facturapi.receipts().downloadPdf( + "rec_123" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $pdfBytes = $facturapi->Receipts->previewToInvoicePdf([ - "keys" => ["ticket_1001", "ticket_1002"], - "customer" => [ - "legal_name" => "Dunder Mifflin", - "tax_id" => "ABC101010111", - "tax_system" => "601", - "address" => [ - "zip" => "85900" - ] - ], - "use" => "G03" - ]); - requestBody: - $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + // stream containing the PDF file + $pdf = $facturapi->Receipts->downloadPdf("58e93bd8e86eb318b019743d"); + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID of the receipt to download security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: PDF binary content + description: E-receipt in PDF format content: - application/pdf: + application/octet-stream: schema: type: string format: binary - "204": - description: No eligible receipts found for the provided keys "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "429": + $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/to-invoice/preview/download-url: - post: - operationId: previewToInvoiceFromReceiptsUrl + /receipts/{receipt_id}/download-url/pdf: + get: + operationId: getReceiptDownloadUrl tags: - receipt - summary: Get receipts invoice preview URL - description: Returns a temporary URL for the PDF preview of an invoice built from the selected receipts. + summary: Get download URL + description: | + Returns an object containing file metadata and a temporary URL to download the receipt in PDF, without the file travelling through your server. + + The URL grants access to that one file while it is valid: treat it as a credential and do not store it. x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - const download = await facturapi.receipts.previewToInvoicePdfUrl({ - keys: ['ticket_1001', 'ticket_1002'], - customer: 'cus_123', - use: 'G03' - }); + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.receipts.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); + console.log(download.url, download.expires_at); - requestBody: - $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID of the object to download security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the PDF preview. + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. content: application/json: schema: @@ -6472,69 +6754,75 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/global-invoice: + /receipts/{receipt_id}/email: post: - operationId: createGlobalInvoice + operationId: sendReceiptByEmail tags: - receipt - summary: Create global invoice + summary: Send e-receipt by email description: | - Creates a global invoice that will include all receipts with `status = "open"` from a certain period. - - Global invoices are issued to the generic `PUBLICO EN GENERAL` customer. - Included receipts are associated with that customer and their `status` - changes to `"invoiced_globally"`. + Send the e-receipt by email to the customer. - A global invoice can include up to 5,000 open receipts. If the period contains - more, send `limit_to_max_receipts: true` and repeat the request with the same - period until the response is `null`. + The email sent will be customized with the logo and colors of the organization that created it, + and will include a button to invoice the receipt, as well as the receipt attached as a PDF to the message. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/receipts/global-invoice \ + // Send to a different email than the one registered by the customer + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/email \ -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST \ -H "Content-Type: application/json" \ -d '{ - "from": "2021-01-01T05:00:00.000Z", - "to": "2021-01-31T04:59:59.999Z", - "periodicity": "month", - "months": "01", - "year": 2021, - "folio_number": 1234, - "series": "G", - "limit_to_max_receipts": true - }' + "email": "another_email@example.com" + }' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.receipts.createGlobalInvoice({ - from: '2020-12-01T05:00:00.000Z', - to: '2020-12-31T04:59:59.999Z', - periodicity: 'month', - months: '01', - year: 2021, - folio_number: 1234, - series: 'G', - limit_to_max_receipts: true - }); + // Send to a different email than the one registered by the customer + await facturapi.receipts.sendByEmail( + '58e93bd8e86eb318b019743d', + { email: 'ejemplo@correo.com' } + ); + + // Send to multiple emails (max 10) + await facturapi.receipts.sendByEmail( + '58e93bd8e86eb318b019743d', + { + email: [ + 'primer@correo.com', + 'segundo@correo.com' + ] + } + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Receipt.CreateGlobalInvoiceAsync(new Dictionary - { - ["from"] = "2020-12-01T05:00:00.000Z", - ["to"] = "2020-12-31T04:59:59.999Z", - ["periodicity"] = "month", - ["months"] = "01", - ["year"] = 2021, - ["folio_number"] = 1234, - ["series"] = "G" - }); + // Send to a different email than the one registered by the customer + await facturapi.Receipt.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = "ejemplo@correo.com" + } + ); + + // Send to multiple emails (max 10) + await facturapi.Receipt.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = new String[] + { + "primer@correo.com", + "segundo@correo.com" + } + } + ); - lang: Java label: Java source: | @@ -6544,45 +6832,82 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = facturapi.receipts().createGlobalInvoice( + var response = facturapi.receipts().sendByEmail( + "rec_123", Map.of( - "month", 5, - "year", 2024 + "to", "cliente@example.com" ) ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Receipts->createGlobalInvoice([ - "from" => "2020-12-01T05:00:00.000Z", - "to" => "2020-12-31T04:59:59.999Z", - "periodicity" => "month", - "months" => "01", - "year" => 2021, - "folio_number" => 1234, - "series" => "G" - ]); + // Send to a different email than the one registered by the customer + $facturapi->Receipts->sendByEmail( + "58e93bd8e86eb318b019743d", + "ejemplo@correo.com" + ); + + // Send to multiple emails (max 10) + $facturapi->Receipts->sendByEmail( + "58e93bd8e86eb318b019743d", + [ + "primer@correo.com", + "segundo@correo.com" + ] + ); + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID of the e-receipt to send requestBody: - $ref: "#/components/requestBodies/ReceiptCreateGlobalInvoice" + required: false + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + description: | + Email address to send the e-receipt. If not sent, the email registered by the customer will be used. + oneOf: + - type: string + format: email + description: Email address to send the e-receipt. + example: other@email.com + - type: array + example: ["first@email.com", "second@email.com"] + description: | + Array of email addresses to send the e-receipt. The maximum number of emails is 10. + maxLength: 10 + items: + type: string + format: email security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Created `Invoice` object, or `null` when the period has no open receipts + description: Generic response object content: application/json: schema: - oneOf: - - $ref: "#/components/schemas/Invoice" - - type: "null" + type: object + required: + - ok + properties: + ok: + type: boolean + description: Indicates if the email was sent successfully "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -6622,7 +6947,8 @@ paths: "imp_retenidos": [ { "monto_ret": 40, - "base_ret": 250 + "base_ret": 250, + "tipo_pago_ret": "04" } ] } @@ -6646,7 +6972,8 @@ paths: imp_retenidos: [ { monto_ret: 40, - base_ret: 250 + base_ret: 250, + tipo_pago_ret: "04" } ] } @@ -6673,9 +7000,9 @@ paths: { new Dictionary { - ["] ["monto_ret"] = 40, - ["base_ret"] = 250 + ["base_ret"] = 250, + ["tipo_pago_ret"] = "04" } } } @@ -6691,16 +7018,19 @@ paths: var retention = facturapi.retentions().create( Map.of( - "receiver", Map.of( - "name", "Cliente ejemplo" - ), - "items", List.of( - Map.of( - "quantity", 1, - "product", "prod_123" - ) - ) - )); + "customer", "58e93bd8e86eb318b0197456", + "cve_retenc", "26", + "periodo", Map.of("mes_ini", 1, "mes_fin", 12, "ejerc", 2020), + "totales", Map.of( + "monto_tot_operacion", 244.654321, + "monto_tot_exent", 145.123456, + "imp_retenidos", List.of(Map.of( + "monto_ret", 40, + "base_ret", 250, + "tipo_pago_ret", "04" + )) + ) + )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); @@ -6719,7 +7049,8 @@ paths: [ "impuesto" => "ISR", "monto_ret" => 40, - "base_ret" => 250 + "base_ret" => 250, + "tipo_pago_ret" => "04" ] ] ] @@ -6780,16 +7111,16 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // All retentions of the organization - const retentionSearch = await facturapi.retentions.list(); + const retentionSearch1 = await facturapi.retentions.list(); // All retentions issued for a certain customer - const retentionSearch = await facturapi.retentions.list({ + const retentionSearch2 = await facturapi.retentions.list({ customer: '590ce6c56d04f840aa8438af' }); // Page 3 of search results for free text search // of retentions issued between 2017 and 2019 - const retentionSearch = await facturapi.retentions.list({ + const retentionSearch3 = await facturapi.retentions.list({ q: 'John Doe', date: { gte: new Date('2017-01-01T00:00:00.000Z'), @@ -6889,12 +7220,13 @@ paths: items: type: string enum: + - all - draft - pending - valid - canceled - failed - description: Filter by one or more retention statuses. + description: "Filter by one or more retention statuses. If omitted, no status filter is applied, equivalent to `all`. Sending `all` also disables this filter." - $ref: "#/components/parameters/SearchDate" - $ref: "#/components/parameters/SearchPage" - $ref: "#/components/parameters/SearchLimit" @@ -7146,10 +7478,10 @@ paths: schema: type: string enum: - - "01" - - "02" - - "03" - - "04" + - '01' + - '02' + - '03' + - '04' description: | Code representing the reason for the retention cancellation. Required for retentions that are not drafts. @@ -7165,7 +7497,7 @@ paths: description: | ID of the retention that replaces the one being canceled. You can use the Facturapi ID or the fiscal folio (UUID). - + Required for motives 01 and 04. Draft deletion does not require query parameters. security: - "SecretLiveKey": [] - "SecretTestKey": [] @@ -7351,17 +7683,23 @@ paths: // Download PDF and XML compressed in a ZIP file const zipStream = await facturapi.retentions.downloadZip('58e93bd8e86eb318b019743d'); const zipFile = fs.createWriteStream('./retencion.zip'); - zipStream.pipe(zipFile); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(zipFile); + } // Download only the PDF const pdfStream = await facturapi.retentions.downloadPdf('58e93bd8e86eb318b019743d'); const pdfFile = fs.createWriteStream('./retencion.pdf'); - pdfStream.pipe(pdfFile); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } // Download only the XML const xmlStream = await facturapi.retentions.downloadXml('58e93bd8e86eb318b019743d'); const xmlFile = fs.createWriteStream('./retencion.xml'); - xmlStream.pipe(xmlFile); + if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(xmlFile); + } - lang: csharp label: C# source: | @@ -7433,6 +7771,72 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" + /retentions/{retention_id}/download-url/{format}: + get: + operationId: getRetentionDownloadUrl + tags: + - retention + summary: Get download URL + description: | + Returns an object containing file metadata and a temporary URL to download the retention in PDF, XML, or both in a ZIP file, without the file travelling through your server. + + The URL grants access to that one file while it is valid: treat it as a credential and do not store it. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/retentions/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.retentions.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); + + console.log(download.url, download.expires_at); + parameters: + - in: path + name: retention_id + schema: + type: string + required: true + description: ID of the object to download + - in: path + name: format + schema: + type: string + enum: + - pdf + - xml + - zip + required: true + description: Format of the file to download + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Object containing a temporary download URL, its expiration date, the content type, and the filename. + content: + application/json: + schema: + $ref: "#/components/schemas/SignedDownloadUrl" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "409": + $ref: "#/components/responses/Conflict" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" /retentions/{retention_id}/email: post: operationId: sendRetentionByEmail @@ -7608,12 +8012,12 @@ paths: summary: Create organization description: | Create a new Organization that will belong to your user account. - + After creating the organization and before being able to issue invoices with the organization, you will need to finish setting it up by calling the [Update legal data](#tag/organization/operation/editOrganizationLegal) and [Upload certificates (CSD)](#tag/organization/operation/uploadOrganizationCertificate) methods. - + After creating the organization and before you can issue invoices with the organization, you must finish configuring it by calling the methods [Update legal information](#tag/organization/operation/editOrganizationLegal) and @@ -7706,21 +8110,166 @@ paths: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/organizations \ + curl https://www.facturapi.io/v2/organizations \ + -H "Authorization: Bearer sk_user_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const organizationResults = await facturapi.organizations.list(); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Organization.ListAsync(); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var searchResult = facturapi.organizations().list( + Map.of( + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $organizations = $facturapi->Organizations->all() + parameters: + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q + schema: + type: string + description: Free text search. Text to search in `name` (commercial name) or `legal_name` (fiscal name) or `tax_id` (RFC). + - $ref: "#/components/parameters/SearchDate" + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" + security: + - "SecretUserKey": [] + responses: + "200": + description: Search results + content: + application/json: + schema: + $ref: "#/components/schemas/OrganizationSearchResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + + /organizations/me: + get: + operationId: meOrganization + tags: + - organization + summary: Organization detail + description: | + Returns the detail of a organization registered under your account. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/organizations/me \ + -H "Authorization: Bearer sk_user_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const organizationResults = await facturapi.organizations.me(); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Organization.MeAsync(); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var organization = facturapi.organizations().me( + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $organizations = $facturapi->Organizations->me() + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: The `Organization` object + content: + application/json: + schema: + $ref: "#/components/schemas/Organization" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /organizations/{organization_id}: + get: + operationId: getOrganization + tags: + - organization + summary: Retrieve organization by ID + description: | + Retrieve the organization by its ID. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ -H "Authorization: Bearer sk_user_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - const organizationResults = await facturapi.organizations.list(); + const facturapi = new Facturapi('sk_user_API_KEY'); + const organization = await facturapi.organizations.retrieve( + '5a2a307be93a2f00129ea035' + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Organization.ListAsync(); + var facturapi = new FacturapiClient("sk_user_API_KEY"); + var organization = await facturapi.Organization.RetrieveAsync( + "5a2a307be93a2f00129ea035" + ); - lang: Java label: Java source: | @@ -7730,77 +8279,70 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var searchResult = facturapi.organizations().list( - Map.of( - "page", 0, - "limit", 10 - ) + var organization = facturapi.organizations().retrieve( + "org_123" ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - $organizations = $facturapi->Organizations->all() + $facturapi = new Facturapi("sk_user_API_KEY"); + $organization = $facturapi->Organizations->retrieve("5a2a307be93a2f00129ea035"); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q + - in: path + name: organization_id schema: type: string - description: Free text search. Text to search in `name` (commercial name) or `legal_name` (fiscal name) or `tax_id` (RFC). - - $ref: "#/components/parameters/SearchDate" - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + required: true + description: ID of the organization security: + - "SecretLiveKey": [] + - "SecretTestKey": [] - "SecretUserKey": [] responses: "200": - description: Search results + description: "`Organization` object" content: application/json: schema: - $ref: "#/components/schemas/OrganizationSearchResult" + $ref: "#/components/schemas/Organization" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - - /organizations/me: - get: - operationId: meOrganization + delete: + operationId: deleteOrganization tags: - organization - summary: Organization detail + summary: Delete organization description: | - Returns the detail of a organization registered under your account. + Delete the organization from your Facturapi account. Once deleted, you + will not be able to access its resources, such as clients, products, + invoices, receipts, or retentions. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/organizations/me \ + curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ + -X DELETE \ -H "Authorization: Bearer sk_user_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - const organizationResults = await facturapi.organizations.me(); + const facturapi = new Facturapi('sk_user_API_KEY'); + const organization = await facturapi.organizations.del( + '5a2a307be93a2f00129ea035' + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Organization.MeAsync(); + var facturapi = new FacturapiClient("sk_user_API_KEY"); + var organization = await facturapi.Organization.DeleteAsync( + "5a2a307be93a2f00129ea035" + ); - lang: Java label: Java source: | @@ -7810,19 +8352,27 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var organization = facturapi.organizations().me( + var organization = facturapi.organizations().delete( + "org_123" ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - $organizations = $facturapi->Organizations->me() + $facturapi = new Facturapi("sk_user_API_KEY"); + $organization = $facturapi->Organizations->delete( + "5a2a307be93a2f00129ea035" + ); + parameters: + - in: path + name: organization_id + schema: + type: string + required: true + description: ID of the organization security: - - "SecretLiveKey": [] - - "SecretTestKey": [] + - "SecretUserKey": [] responses: "200": - description: The `Organization` object + description: "`Organization` object deleted" content: application/json: schema: @@ -7831,8 +8381,6 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -8239,7 +8787,7 @@ paths: summary: Upload logo description: | Upload the organization's logo. The logo will be displayed on the PDFs and emails sent to your customers. - + The file must be an image in JPG or PNG format and have a size not greater than 500 KB. The recommended dimensions are 800 × 500px. If the organization already has a logo, this call replaces the previous logo. @@ -8803,159 +9351,10 @@ paths: - lang: PHP source: | $facturapi = new Facturapi("sk_user_API_KEY"); - - $organization = $facturapi->Organizations->updateDomain( - "5a2a307be93a2f00129ea035", - [ "domain" => "empresa-demo" ] - ); - parameters: - - in: path - name: organization_id - schema: - type: string - required: true - description: ID of the organization - requestBody: - $ref: "#/components/requestBodies/OrganizationEditDomain" - security: - - "SecretLiveKey": [] - - "SecretUserKey": [] - responses: - "200": - description: Modified `Organization` object - content: - application/json: - schema: - $ref: "#/components/schemas/Organization" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /organizations/{organization_id}: - get: - operationId: getOrganization - tags: - - organization - summary: Retrieve organization by ID - description: | - Retrieve the organization by its ID. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ - -H "Authorization: Bearer sk_user_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_user_API_KEY'); - const organization = await facturapi.organizations.retrieve( - '5a2a307be93a2f00129ea035' - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_user_API_KEY"); - var organization = await facturapi.Organization.RetrieveAsync( - "5a2a307be93a2f00129ea035" - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var organization = facturapi.organizations().retrieve( - "org_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_user_API_KEY"); - $organization = $facturapi->Organizations->retrieve("5a2a307be93a2f00129ea035"); - parameters: - - in: path - name: organization_id - schema: - type: string - required: true - description: ID of the organization - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - - "SecretUserKey": [] - responses: - "200": - description: "`Organization` object" - content: - application/json: - schema: - $ref: "#/components/schemas/Organization" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - delete: - operationId: deleteOrganization - tags: - - organization - summary: Delete organization - description: | - Delete the organization from your Facturapi account. Once deleted, you - will not be able to access its resources, such as clients, products, - invoices, receipts, or retentions. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ - -X DELETE \ - -H "Authorization: Bearer sk_user_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_user_API_KEY'); - const organization = await facturapi.organizations.del( - '5a2a307be93a2f00129ea035' - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_user_API_KEY"); - var organization = await facturapi.Organization.DeleteAsync( - "5a2a307be93a2f00129ea035" - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var organization = facturapi.organizations().delete( - "org_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_user_API_KEY"); - $organization = $facturapi->Organizations->delete( - "5a2a307be93a2f00129ea035" + + $organization = $facturapi->Organizations->updateDomain( + "5a2a307be93a2f00129ea035", + [ "domain" => "empresa-demo" ] ); parameters: - in: path @@ -8964,11 +9363,14 @@ paths: type: string required: true description: ID of the organization + requestBody: + $ref: "#/components/requestBodies/OrganizationEditDomain" security: + - "SecretLiveKey": [] - "SecretUserKey": [] responses: "200": - description: "`Organization` object deleted" + description: Modified `Organization` object content: application/json: schema: @@ -8977,6 +9379,8 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -9193,6 +9597,10 @@ paths: type: array items: type: object + required: + - id + - first_12 + - created_at properties: first_12: type: string @@ -9406,7 +9814,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const seriesList = await facturapi.organizations.getSeries( + const seriesList = await facturapi.organizations.listSeriesGroup( '5a2a307be93a2f00129ea035' ); - lang: csharp @@ -9465,7 +9873,7 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - + post: operationId: createSeriesGroup tags: @@ -9493,7 +9901,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const newSeries = await facturapi.organizations.createSeries( + const newSeries = await facturapi.organizations.createSeriesGroup( '5a2a307be93a2f00129ea035', { series: 'New', @@ -9692,13 +10100,13 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const updatedSeries = await facturapi.organizations.updateSeries( + const updatedSeries = await facturapi.organizations.updateSeriesGroup( '5a2a307be93a2f00129ea035', 'New', - [ - "next_folio" => 1, - "next_folio_test" => 1 - ] + { + next_folio: 1, + next_folio_test: 1 + } ); - lang: csharp label: C# @@ -9788,7 +10196,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const deletedSeries = await facturapi.organizations.deleteSeries( + const deletedSeries = await facturapi.organizations.deleteSeriesGroup( '5a2a307be93a2f00129ea035', 'New' ); @@ -9924,7 +10332,7 @@ paths: summary: Invite user to organization description: | Creates or updates a user invite. By default, invited users get full admin access; to limit access, create a role and send its ID in `role`. - + Each organization can invite one user at no additional cost. Starting from the second invited user, each additional user will incur a monthly fee. This charge is applied automatically when the user accepts the invitation, whether from the dashboard or via the API. You can check the current pricing on our [pricing page](https://www.facturapi.io/pricing). x-codeSamples: @@ -11037,9 +11445,9 @@ paths: summary: Create webhook description: | Register a new webhook in your Facturapi organization. - + Use this call to receive notifications of asynchronous events to the API. - + Test and live environment webhooks are independent. x-codeSamples: - lang: Bash @@ -11057,258 +11465,19 @@ paths: source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.create({ - "enabled_events": ["receipt.self_invoice_complete"], - "url": "http://webhook_api.com" - }); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.CreateAsync(new Dictionary - { - ["enabled_events"] = new Dictionary["receipt.self_invoice_complete"], - ["url"] = "http://webhook_api.com" - }); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var webhook = facturapi.webhooks().create( - Map.of( - "url", "https://example.com/webhooks", - "triggers", List.of("invoice.created") - )); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->create([ - "enabled_events" => ["receipt.self_invoice_complete"], - "url" => "http://webhook_api.com" - ]); - requestBody: - $ref: "#/components/requestBodies/WebhookCreate" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "201": - description: New `Webhook` object - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "200": - description: An existing `Webhook` object with the same URL was found - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - get: - operationId: listWebhooks - tags: - - webhooks - summary: List webhooks - description: | - Returns a list of webhooks created previously for the organization. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -G \ - -d 'page=1' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const searchResult = await facturapi.webhooks.list({ - limit: 0, - page: 1 - }); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var searchResult = await facturapi.Webhook.ListAsync(new Dictionary - { - ["page"] = 1 - ["limit"] = 0, - }); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var searchResult = facturapi.webhooks().list( - Map.of( - "page", 0, - "limit", 10 - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $searchResult = $facturapi->Webhooks->all([ - "page" => 1 - ]); - parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Search results - content: - application/json: - schema: - $ref: "#/components/schemas/WebhookSearchResult" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - - /webhooks/{webhook_id}: - get: - operationId: getWebhook - tags: - - webhooks - summary: Retrieve webhook by ID - description: | - Retrieve the webhook subscription by its ID. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.retrieve('590ce6c56d04f840aa8438af'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.RetrieveAsync("590ce6c56d04f840aa8438af"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var webhook = facturapi.webhooks().retrieve( - "whk_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->retrieve( "5a3ee743f508333611ad6b3c" ); - parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID of the webhook - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: "`Webhook` object" - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - put: - operationId: editWebhook - tags: - - webhooks - summary: Edit webhook - description: | - Update the information of an existing webhook with the parameters you send in the request. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -X PUT - -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "status": "disabled", - "enabled_events": ["receipt.self_invoice_complete"] - }' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.update( - '590ce6c56d04f840aa8438af', - { - "status": "disabled", - "enabled_events": ["receipt.self_invoice_complete"] - } - ); + const customer = await facturapi.webhooks.create({ + "enabled_events": ["receipt.self_invoice_complete"], + "url": "http://webhook_api.com" + }); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.UpdateAsync( - "590ce6c56d04f840aa8438af", - new Dictionary - { - ["status"] = "disabled", - ["address"] = new Dictionary["receipt.self_invoice_complete"] - } - ); + var customer = await facturapi.Webhook.CreateAsync(new Dictionary + { + ["enabled_events"] = new string[] { "receipt.self_invoice_complete" }, + ["url"] = "http://webhook_api.com" + }); - lang: Java label: Java source: | @@ -11318,33 +11487,26 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var webhook = facturapi.webhooks().update("whk_123", Map.of( + var webhook = facturapi.webhooks().create( + Map.of( "url", "https://example.com/webhooks", - "triggers", List.of("invoice.created") + "enabled_events", List.of("receipt.self_invoice_complete") )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->update("590ce6c56d04f840aa8438af", [ - "status" => "disabled", - "address" => ["receipt.self_invoice_complete"] - ] + $customer = $facturapi->Webhooks->create([ + "enabled_events" => ["receipt.self_invoice_complete"], + "url" => "http://webhook_api.com" ]); - parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID of the webhook requestBody: - $ref: "#/components/requestBodies/WebhookEdit" + $ref: "#/components/requestBodies/WebhookCreate" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: - "200": - description: "`Webhook` object edited successfully" + "201": + description: New `Webhook` object content: application/json: schema: @@ -11353,35 +11515,45 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - delete: - operationId: deleteWebhook + get: + operationId: listWebhooks tags: - webhooks - summary: Delete Webhook + summary: List webhooks description: | - Deletes the webhook subscription from the organization. + Returns a list of webhooks created previously for the organization. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -X DELETE \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -G \ + -d 'page=1' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const removedCustomer = await facturapi.webhooks.del('590ce6c56d04f840aa8438af'); + const searchResult = await facturapi.webhooks.list({ + limit: 0, + page: 1 + }); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.DeleteAsync("590ce6c56d04f840aa8438af"); + var searchResult = await facturapi.Webhook.ListAsync(new Dictionary + { + ["page"] = 1 + ["limit"] = 0, + }); - lang: Java label: Java source: | @@ -11391,81 +11563,70 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var webhook = facturapi.webhooks().delete( - "whk_123" + var searchResult = facturapi.webhooks().list( + Map.of( + "page", 0, + "limit", 10 + ) ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $facturapi->Webhooks->delete( "5a3fefd9f508333611ad6b43" ); + $searchResult = $facturapi->Webhooks->all([ + "page" => 1 + ]); parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID of the webhook + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: "`Webhook` object deleted" + description: Search results content: application/json: schema: - $ref: "#/components/schemas/Webhook" + $ref: "#/components/schemas/WebhookSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /webhooks/validate-signature: - post: - operationId: validateWebhookSignature + /webhooks/{webhook_id}: + get: + operationId: getWebhook tags: - webhooks - summary: Validate Webhook Signature + summary: Retrieve webhook by ID description: | - Validate the signature of an event object received through a Webhook. - Use this operation to verify the authenticity and integrity of the event - received, comparing the received signature with the one generated by Facturapi. + Retrieve the webhook subscription by its ID. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/webhooks/validate-signature \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "secret": "wh_sec...", - "payload": "Object Response", - "signature": "Signature_FROM_HEADER" - }' + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.validateSignature({ - secret: "wh_sec...", - payload: "Object Response", - signature: "Signature_FROM_HEADER" - }); + const customer = await facturapi.webhooks.retrieve('590ce6c56d04f840aa8438af'); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.ValidateSignatureAsync(new Dictionary - { - ["secret"] = "wh_sec...", - ["payload"] = new Dictionary["Object Response"], - ["signature"] = "Signature_FROM_HEADER" - }); + var customer = await facturapi.Webhook.RetrieveAsync("590ce6c56d04f840aa8438af"); - lang: Java label: Java source: | @@ -11475,138 +11636,81 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var event = facturapi.webhooks().validateSignature( - "webhook_secret", - "signature_hex", - "{\"id\":\"evt_123\"}" - ); + var webhook = facturapi.webhooks().retrieve( + "whk_123" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->validateSignature([ - "secret" => "wh_sec...", - "payload" => "Object Response", - "signature" => "Signature_FROM_HEADER" - ]); - requestBody: - content: - application/json: - schema: - type: object - properties: - secret: - type: string - description: Secret key of the webhook, found in the webhook settings or upon creation. - payload: - type: object - description: Event object received through a webhook. - signature: - type: string - description: Signature from the header "Facturapi-Signature". + $customer = $facturapi->Webhooks->retrieve( "5a3ee743f508333611ad6b3c" ); + parameters: + - in: path + name: webhook_id + schema: + type: string + required: true + description: ID of the webhook security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Event object successfully validated + description: "`Webhook` object" content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - example: "invoice.status_updated" - enum: - - invoice.status_updated - data: - type: object - properties: - type: - type: string - description: Type of object affected by the event - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - - - /check: - get: - tags: - - tools - summary: Health check - description: | - Check the health of the Facturapi API. - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: API is operational - content: - application/json: - schema: - type: object - properties: - ok: - type: boolean - example: true - "401": - description: Error de autenticación. Asegúrate de estar usando tu llave secreta. - "502": - description: Servicio temporalmente no disponible. - - /tools/tax_id_validation: - get: + put: + operationId: editWebhook tags: - - tools - summary: Validate RFC (tax_id) + - webhooks + summary: Edit webhook description: | - Check the status of an RFC in the list of **EFOS** (Empresas que - Facturan Operaciones Simuladas). When appearing in this list, the RFC is - or was suspected of engaging in simulated fiscal operations (factureras). - - The response (detailed below) includes the results of this validation. - It includes the boolean property `is_valid`, which Facturapi resolves by - interpreting the response. A value of `true` for this property indicates - that the RFC has no issues to resolve and is free of problems; and the - opposite for `false`. - - Additionally, you can check the `data` property to see the raw values of - the query to the SAT. + Update the information of an existing webhook with the parameters you send in the request. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/tools/tax_id_validation?tax_id=BBA830831LJ2 \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -X PUT + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "status": "disabled", + "enabled_events": ["receipt.self_invoice_complete"] + }' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - - const validation = await facturapi.tools.validateTaxId('BBA830831LJ2'); + const customer = await facturapi.webhooks.update( + '590ce6c56d04f840aa8438af', + { + "status": "disabled", + "enabled_events": ["receipt.self_invoice_complete"] + } + ); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var customer = await facturapi.Tool.ValidateTaxIdAsync("BBA830831LJ2"); + var customer = await facturapi.Webhook.UpdateAsync( + "590ce6c56d04f840aa8438af", + new Dictionary + { + ["status"] = "disabled", + ["enabled_events"] = new string[] { "receipt.self_invoice_complete" } + } + ); - lang: Java label: Java source: | @@ -11616,32 +11720,36 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var validation = facturapi.tools().validateTaxId( - "XAXX010101000" - ); + var webhook = facturapi.webhooks().update("whk_123", Map.of( + "status", "disabled", + "enabled_events", List.of("receipt.self_invoice_complete") + )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $customer = $facturapi->Tools->validateTaxId("BBA830831LJ2"); + $customer = $facturapi->Webhooks->update("590ce6c56d04f840aa8438af", [ + "status" => "disabled", + "enabled_events" => ["receipt.self_invoice_complete"] + ]); parameters: - - in: query - name: tax_id - required: true + - in: path + name: webhook_id schema: type: string - description: RFC a validar - example: BBA830831LJ2 + required: true + description: ID of the webhook + requestBody: + $ref: "#/components/requestBodies/WebhookEdit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Validation result + description: "`Webhook` object edited successfully" content: application/json: schema: - $ref: "#/components/schemas/TaxIdValidationResult" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": @@ -11650,38 +11758,31 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /catalogs/products: - get: + delete: + operationId: deleteWebhook tags: - - sat_keys - summary: Product/Service Key - description: Search in the SAT Product/Service catalog, which contains the key to include in the invoice. + - webhooks + summary: Delete Webhook + description: | + Deletes the webhook subscription from the organization. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/catalogs/products?q=ukelele \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -X DELETE \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - - const searchResult = await facturapi.catalogs.searchProducts({ - q: 'ukelele' - }); + const removedCustomer = await facturapi.webhooks.del('590ce6c56d04f840aa8438af'); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Catalog.SearchProducts( - new Dictionary - { - ["q"] = "ukelele" - } - ); + var customer = await facturapi.Webhook.DeleteAsync("590ce6c56d04f840aa8438af"); - lang: Java label: Java source: | @@ -11691,84 +11792,91 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var result = facturapi.catalogs().searchProducts( - Map.of( - "q", "0101", - "page", 0, - "limit", 10 - ) + var webhook = facturapi.webhooks().delete( + "whk_123" ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $result = $facturapi->Catalogs->searchProducts([ - "q" => "ukelele" - ]); + $facturapi->Webhooks->delete( "5a3fefd9f508333611ad6b43" ); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q + - in: path + name: webhook_id schema: type: string - description: Text search. Text to search in the product/service classification description. - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + required: true + description: ID of the webhook security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Search results + description: "`Webhook` object deleted" content: application/json: schema: - $ref: "#/components/schemas/ProductCatalogSearchResult" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /catalogs/units: - get: + + /webhooks/validate-signature: + post: + operationId: validateWebhookSignature tags: - - sat_keys - summary: Units of Measure - description: Search in the SAT Units of Measure catalog. + - webhooks + summary: Validate Webhook Signature + description: | + Validate the signature of an event object received through a Webhook. + Use this operation to verify the authenticity and integrity of the event + received, comparing the received signature with the one generated by Facturapi. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/catalogs/units?q=pulgada \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/validate-signature \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "secret": "wh_sec...", + "payload": "Object Response", + "signature": "Signature_FROM_HEADER" + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' + import Facturapi from 'facturapi'; const facturapi = new Facturapi('sk_test_API_KEY'); - const searchResult = await facturapi.catalogs.searchUnits({ - q: 'pulgada' - }); + // Pass the original, unparsed body and the signature from the Facturapi-Signature header. + /** + * @param {string | Uint8Array | ArrayBuffer} rawBody + * @param {string} signature + * @param {string} secret + */ + export async function verifyWebhook(rawBody, signature, secret) { + const event = await facturapi.webhooks.validateSignature({ + secret, + signature, + payload: rawBody + }); + return event; + } - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Catalog.SearchUnits( - new Dictionary - { - ["q"] = "pulgada" - } - ); + var customer = await facturapi.Webhook.ValidateSignatureAsync(new Dictionary + { + ["secret"] = "wh_sec...", + ["payload"] = new Dictionary["Object Response"], + ["signature"] = "Signature_FROM_HEADER" + }); - lang: Java label: Java source: | @@ -11778,42 +11886,56 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var result = facturapi.catalogs().searchUnits( - Map.of( - "q", "H87", - "page", 0, - "limit", 10 - ) - ); + var event = facturapi.webhooks().validateSignature( + "webhook_secret", + "signature_hex", + "{\"id\":\"evt_123\"}" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $result = $facturapi->Catalogs->searchUnits([ - "q" => "pulgada" + $customer = $facturapi->Webhooks->validateSignature([ + "secret" => "wh_sec...", + "payload" => "Object Response", + "signature" => "Signature_FROM_HEADER" ]); - parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q - schema: - type: string - description: Query. Text to search in the description of the unit of measure. - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + secret: + type: string + description: Secret key of the webhook, found in the webhook settings or upon creation. + payload: + oneOf: + - type: string + - type: object + additionalProperties: true + description: "Signed payload. Prefer the original JSON text, preserving the exact bytes received. Objects are also accepted, but verification uses their JSON serialization." + signature: + type: string + description: Signature from the header "Facturapi-Signature". + required: + - secret + - payload + - signature security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Search results + description: Original payload with a valid signature content: application/json: schema: - $ref: "#/components/schemas/UnitCatalogSearchResult" + oneOf: + - type: string + - type: object + additionalProperties: true + description: "Returns the original payload when the signature is valid: a string for JSON text, or an object for object input. It does not parse a string into an object." "400": $ref: "#/components/responses/BadRequest" "401": @@ -11824,179 +11946,193 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/download-url/{format}: - get: - operationId: getInvoiceDownloadUrl - tags: - - invoice - summary: Get download URL - description: | - Returns a temporary URL to download the invoice in PDF, XML, or both in a ZIP file, without the file travelling through your server. - - The URL grants access to that one file while it is valid: treat it as a credential and do not store it. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi'; - const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.invoices.downloadPdfUrl( - '58e93bd8e86eb318b019743d' - ); - console.log(download.url, download.expires_at); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID of the object to download - - in: path - name: format - schema: - type: string - enum: - - pdf - - xml - - zip - required: true - description: Format of the file to download + /check: + get: + operationId: "checkApiHealth" + tags: + - tools + summary: Health check + description: "Checks that the API is available. This endpoint requires a secret API key." security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the CFDI in the requested format + description: API is operational content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" - "400": - $ref: "#/components/responses/BadRequest" + type: object + properties: + ok: + type: boolean + example: true "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "409": - $ref: "#/components/responses/Conflict" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/cancellation_receipt/download-url/{format}: + description: Error de autenticación. Asegúrate de estar usando tu llave secreta. + "502": + description: Servicio temporalmente no disponible. + + /tools/tax_id_validation: get: - operationId: getCancellationReceiptDownloadUrl + operationId: validateTaxId tags: - - invoice - summary: Get cancellation receipt download URL + - tools + summary: Validate RFC (tax_id) description: | - Returns a temporary URL to download the XML or PDF receipt issued by SAT when a cancellation request is submitted through Facturapi, without the file travelling through your server. The receipt contains the immediate request result and does not necessarily prove that the CFDI is already canceled; check the invoice status to confirm the outcome. + Check the status of an RFC in the list of **EFOS** (Empresas que + Facturan Operaciones Simuladas). When appearing in this list, the RFC is + or was suspected of engaging in simulated fiscal operations (factureras). + + The response (detailed below) includes the results of this validation. + It includes the boolean property `is_valid`, which Facturapi resolves by + interpreting the response. A value of `true` for this property indicates + that the RFC has no issues to resolve and is free of problems; and the + opposite for `false`. - The URL grants access to that one file while it is valid: treat it as a credential and do not store it. + Additionally, you can check the `data` property to see the raw values of + the query to the SAT. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/download-url/pdf \ + curl https://www.facturapi.io/v2/tools/tax_id_validation?tax_id=BBA830831LJ2 \ -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.invoices.downloadCancellationReceiptPdfUrl( - '58e93bd8e86eb318b019743d' - ); - console.log(download.url, download.expires_at); + const validation = await facturapi.tools.validateTaxId('BBA830831LJ2'); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var customer = await facturapi.Tool.ValidateTaxIdAsync("BBA830831LJ2"); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var validation = facturapi.tools().validateTaxId( + "XAXX010101000" + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $customer = $facturapi->Tools->validateTaxId("BBA830831LJ2"); parameters: - - in: path - name: invoice_id - schema: - type: string + - in: query + name: tax_id required: true - description: ID of the object to download - - in: path - name: format schema: type: string - enum: - - xml - - pdf - required: true - description: Format of the cancellation receipt + description: RFC a validar + example: BBA830831LJ2 security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the cancellation receipt in the requested format + description: Validation result content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/TaxIdValidationResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/download-url/pdf: + /catalogs/products: get: - operationId: getReceiptDownloadUrl + operationId: searchProducts tags: - - receipt - summary: Get download URL - description: | - Returns a temporary URL to download the receipt in PDF, without the file travelling through your server. - - The URL grants access to that one file while it is valid: treat it as a credential and do not store it. + - sat_keys + summary: Product/Service Key + description: Search in the SAT Product/Service catalog, which contains the key to include in the invoice. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/catalogs/products?q=ukelele \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.receipts.downloadPdfUrl( - '58e93bd8e86eb318b019743d' + + const searchResult = await facturapi.catalogs.searchProducts({ + q: 'ukelele' + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Catalog.SearchProducts( + new Dictionary + { + ["q"] = "ukelele" + } ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - console.log(download.url, download.expires_at); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var result = facturapi.catalogs().searchProducts( + Map.of( + "q", "0101", + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $result = $facturapi->Catalogs->searchProducts([ + "q" => "ukelele" + ]); parameters: - - in: path - name: receipt_id + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q schema: type: string - required: true - description: ID of the object to download + description: Text search. Text to search in the product/service classification description. + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the receipt in PDF + description: Search results content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/ProductCatalogSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": @@ -12007,74 +12143,96 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /retentions/{retention_id}/download-url/{format}: + /catalogs/units: get: - operationId: getRetentionDownloadUrl + operationId: searchUnits tags: - - retention - summary: Get download URL - description: | - Returns a temporary URL to download the retention in PDF, XML, or both in a ZIP file, without the file travelling through your server. - - The URL grants access to that one file while it is valid: treat it as a credential and do not store it. + - sat_keys + summary: Units of Measure + description: Search in the SAT Units of Measure catalog. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/retentions/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/catalogs/units?q=pulgada \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.retentions.downloadPdfUrl( - '58e93bd8e86eb318b019743d' + + const searchResult = await facturapi.catalogs.searchUnits({ + q: 'pulgada' + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Catalog.SearchUnits( + new Dictionary + { + ["q"] = "pulgada" + } ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - console.log(download.url, download.expires_at); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var result = facturapi.catalogs().searchUnits( + Map.of( + "q", "H87", + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $result = $facturapi->Catalogs->searchUnits([ + "q" => "pulgada" + ]); parameters: - - in: path - name: retention_id - schema: - type: string - required: true - description: ID of the object to download - - in: path - name: format + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q schema: type: string - enum: - - pdf - - xml - - zip - required: true - description: Format of the file to download + description: Query. Text to search in the description of the unit of measure. + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Temporary download URL for the retention in the requested format + description: Search results content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/UnitCatalogSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" "404": $ref: "#/components/responses/NotFound" - "409": - $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" -x-webhooks: - "Global invoice created": +webhooks: + invoice.global_invoice_created: post: summary: Global invoice created description: | @@ -12086,27 +12244,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - example: "invoice.global_invoice_created" - enum: - - invoice.global_invoice_created - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - "Invoice status updated": + $ref: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + operationId: onInvoiceGlobalInvoiceCreated + responses: + '200': + description: OK + invoice.status_updated: post: summary: Invoice status updated description: | @@ -12120,37 +12263,13 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - example: "invoice.status_updated" - enum: - - invoice.status_updated - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - related_resource_messages: - type: array - description: Messages related to the resource associated with the event. - items: - $ref: "#/components/schemas/RelatedResourceMessage" + $ref: '#/components/schemas/InvoiceStatusUpdatedEvent' examples: with_related_messages: summary: With related messages value: id: evt_xxx - created_at: "2026-07-01T12:00:00.000Z" + created_at: '2026-07-01T12:00:00.000Z' livemode: true organization: org_xxx type: invoice.status_updated @@ -12164,12 +12283,12 @@ x-webhooks: source: stamping_async_task severity: error message: The receiver RFC is not valid - created_at: "2026-01-01T00:00:00.000Z" + created_at: '2026-01-01T00:00:00.000Z' without_related_messages: summary: Without related messages value: id: evt_xxx - created_at: "2026-07-01T12:00:00.000Z" + created_at: '2026-07-01T12:00:00.000Z' livemode: true organization: org_xxx type: invoice.status_updated @@ -12178,7 +12297,11 @@ x-webhooks: object: id: invoice_xxx related_resource_messages: [] - "Invoice created from dashboard": + operationId: onInvoiceStatusUpdated + responses: + '200': + description: OK + invoice.created_from_dashboard: post: summary: Invoice created from dashboard description: | @@ -12190,28 +12313,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - example: "invoice.created_from_dashboard" - enum: - - invoice.created_from_dashboard - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - - "Cancellation status updated": + $ref: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + operationId: onInvoiceCreatedFromDashboard + responses: + '200': + description: OK + invoice.cancellation_status_updated: post: tags: - events @@ -12223,26 +12330,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - enum: - - invoice.cancellation_status_updated - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - "Self-invoice completed": + $ref: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + operationId: onInvoiceCancellationStatusUpdated + responses: + '200': + description: OK + receipt.self_invoice_complete: post: tags: - events @@ -12254,27 +12347,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - example: "receipt.self_invoice_complete" - enum: - - receipt.self_invoice_complete - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - receipt - object: - $ref: "#/components/schemas/Receipt" - "Receipt status updated": + $ref: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + operationId: onReceiptSelfInvoiceComplete + responses: + '200': + description: OK + receipt.status_updated: post: tags: - events @@ -12286,25 +12364,26 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Type of event - enum: - - receipt.status_updated - data: - type: object - properties: - type: - type: string - description: Type of object associated with the event - enum: - - receipt - object: - $ref: "#/components/schemas/Receipt" + $ref: '#/components/schemas/ReceiptStatusUpdatedEvent' + operationId: onReceiptStatusUpdated + responses: + '200': + description: OK + customer.edit_link_completed: + post: + summary: Customer edit completed + tags: + - events + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEditLinkCompletedEvent' + responses: + '200': + description: OK + operationId: onCustomerEditLinkCompleted components: responses: BadRequest: @@ -12436,7 +12515,7 @@ components: application/json: schema: allOf: - - $ref: "#/components/schemas/ProductProperties" + - $ref: "#/components/schemas/ProductEditableProperties" InvoiceCreate: required: true content: @@ -12459,7 +12538,7 @@ components: content: application/json: schema: - oneOf: + anyOf: - $ref: "#/components/schemas/InvoiceIngresoEditInput" - $ref: "#/components/schemas/InvoiceEgresoEditInput" - $ref: "#/components/schemas/InvoicePagoEditInput" @@ -12655,7 +12734,7 @@ components: schema: type: integer minimum: 1 - default: 50 + default: 100 maximum: 100 description: Number from 1 to 100 representing the maximum amount of results to return for pagination purposes. @@ -12686,9 +12765,219 @@ components: Returns the results before the given cursor. Only with `pagination=cursor`; mutually exclusive with `after`. schemas: + DateOrDateTime: + description: Date in YYYY-MM-DD format or an ISO8601 date and time. + anyOf: + - type: string + format: date + - type: string + format: date-time + InvoiceGlobalInvoiceCreatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + example: invoice.global_invoice_created + enum: + - invoice.global_invoice_created + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + example: invoice.status_updated + enum: + - invoice.status_updated + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceCreatedFromDashboardEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + example: invoice.created_from_dashboard + enum: + - invoice.created_from_dashboard + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceCancellationStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + enum: + - invoice.cancellation_status_updated + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + ReceiptSelfInvoiceCompleteEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + example: receipt.self_invoice_complete + enum: + - receipt.self_invoice_complete + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - receipt + object: + $ref: '#/components/schemas/Receipt' + required: + - type + - object + required: + - type + - data + ReceiptStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Type of event + enum: + - receipt.status_updated + data: + type: object + properties: + type: + type: string + description: Type of object associated with the event + enum: + - receipt + object: + $ref: '#/components/schemas/Receipt' + required: + - type + - object + required: + - type + - data + CustomerEditLinkCompletedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + enum: + - customer.edit_link_completed + data: + type: object + properties: + type: + type: string + enum: + - customer + object: + $ref: '#/components/schemas/Customer' + required: + - type + - object + required: + - type + - data + ApiEvent: + oneOf: + - $ref: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + - $ref: '#/components/schemas/InvoiceStatusUpdatedEvent' + - $ref: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + - $ref: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + - $ref: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + - $ref: '#/components/schemas/ReceiptStatusUpdatedEvent' + - $ref: '#/components/schemas/CustomerEditLinkCompletedEvent' + discriminator: + propertyName: type + mapping: + invoice.global_invoice_created: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + invoice.status_updated: '#/components/schemas/InvoiceStatusUpdatedEvent' + invoice.created_from_dashboard: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + invoice.cancellation_status_updated: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + receipt.self_invoice_complete: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + receipt.status_updated: '#/components/schemas/ReceiptStatusUpdatedEvent' + customer.edit_link_completed: '#/components/schemas/CustomerEditLinkCompletedEvent' SignedDownloadUrl: type: object - description: Temporary download URL for a file. + description: Object containing a temporary download link and file metadata. required: - url - expires_at @@ -12697,6 +12986,7 @@ components: properties: url: type: string + format: uri description: Download URL. It grants access to the file while it is valid. expires_at: type: string @@ -12753,7 +13043,7 @@ components: type: string format: date-time description: Creation date and time of the event - example: 2022-03-30T00:00:00Z + example: '2022-03-30T00:00:00Z' livemode: type: boolean description: Indicates if the event was generated in Test mode (false) or Live mode (true). @@ -12762,6 +13052,16 @@ components: type: string description: ID of the organization this event is related to example: 61f81a7fbd4661b11b9b3f27 + related_resource_messages: + type: array + description: Messages related to the resource associated with the event. + items: + $ref: '#/components/schemas/RelatedResourceMessage' + required: + - id + - created_at + - livemode + - organization DateRange: type: object properties: @@ -12884,12 +13184,14 @@ components: type: integer example: 1 title: Página - description: The current page number within the search results + description: "Page number. It is 0 when there are no matches. Omitted on every cursor-pagination response, including the first page." + minimum: 0 total_pages: type: integer example: 1 title: Total pages - description: The total number of pages available in the search results + description: "Total number of pages. Omitted on every cursor-pagination response, including the first page." + minimum: 0 total_results: type: integer example: 1 @@ -12897,12 +13199,16 @@ components: description: | The total number of results available in the search. In `pagination=cursor` mode it is only included on the first page of the search (no `after`/`before`); the total does not change between pages. previous_cursor: - type: [string, "null"] + type: + - string + - 'null' example: null title: Previous cursor description: Cursor to fetch the previous page of results. It is `null` on the first page. Only available with `pagination=cursor`. next_cursor: - type: [string, "null"] + type: + - string + - 'null' example: null title: Next cursor description: Cursor to fetch the next page of results. It is `null` when there are no more results. Only available with `pagination=cursor`. @@ -13022,14 +13328,14 @@ components: example: 08/06/2021 format: "DD/MM/YYYY" description: Date of favorable sentence. - + ProductCatalogResult: type: object properties: key: type: string description: Key from the SAT catalog - example: 60131324 + example: "60131324" description: type: string description: Description @@ -13062,6 +13368,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -13071,6 +13379,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -13094,7 +13404,7 @@ components: type: string description: Description of the catalog entry - + LocalTax: type: object required: @@ -13103,12 +13413,11 @@ components: properties: rate: type: number - example: 0.10 + example: 0.1 description: Tax rate in decimal format. base: type: number - default: 100% of subtotal - description: Tax base amount. + description: "Tax base. If omitted, the full subtotal of the line item is used." type: type: string description: Tax name. Free text. @@ -13116,6 +13425,12 @@ components: type: boolean default: false description: Indicates if it is a withholding tax (`true`) or a transferred tax (`false`). + factor: + type: string + enum: + - Tasa + - Cuota + - Exento BaseTax: title: Tax type: object @@ -13134,8 +13449,7 @@ components: description: Tax rate in decimal format. base: type: number - default: 100% of subtotal - description: Tax base amount. + description: "Tax base. If omitted, it is calculated from the line item subtotal and tax factor. For the Cuota factor, the number of units is used." type: type: string default: IVA @@ -13144,6 +13458,8 @@ components: - IVA - ISR - IEPS + ieps_mode: + $ref: "#/components/schemas/IepsMode" factor: type: string default: Tasa @@ -13156,33 +13472,40 @@ components: type: boolean default: false description: Indicates if it is a withholding tax (`true`) or a transferred tax (`false`). + IepsMode: + type: string + default: sum_before_taxes + enum: + - sum_before_taxes + - break_down + - unit + - subtract_before_break_down + description: | + Indicates in which way the tax is calculated. + + `"sum_before_taxes"`: Apply the IEPS to the subtotal first and use the result as the base for the rest of the taxes in the product. + + `"break_down"`: Charge and break down the IEPS at the same level as the rest of the taxes in the product. + + `"unit"`: Apply the IEPS before the unit price, and use the original unit price as the base for the rest of the taxes. + + `"subtract_before_break_down"`: Apply the IEPS only to calculate taxes like IVA de traslado and retentions, and use the original unit price as the base for the rest of the taxes. + + Consult with your accountant which case applies to your company and product. + IepsTax: type: object allOf: - $ref: "#/components/schemas/BaseTax" - type: object + required: + - type properties: - ieps_mode: + type: type: string - default: sum_before_taxes - enum: - - sum_before_taxes - - break_down - - unit - - subtract_before_break_down - description: | - Indicates in which way the tax is calculated. - - `"sum_before_taxes"`: Apply the IEPS to the subtotal first and use the result as the base for the rest of the taxes in the product. - - `"break_down"`: Charge and break down the IEPS at the same level as the rest of the taxes in the product. - - `"unit"`: Apply the IEPS before the unit price, and use the original unit price as the base for the rest of the taxes. - - `"subtract_before_break_down"`: Apply the IEPS only to calculate taxes like IVA de traslado and retentions, and use the original unit price as the base for the rest of the taxes. - - Consult with your accountant which case applies to your company and product. - + const: IEPS + ieps_mode: + $ref: "#/components/schemas/IepsMode" Stamp: type: object description: Information about the digital stamp added by the PAC. @@ -13192,8 +13515,8 @@ components: description: Digital signature of the fiscal document. date: type: string - format: date-time - description: Stamp date in ISO8601 format (UTC String). + description: "SAT FechaTimbrado: local date and time without a timezone offset. Preserved as text." + example: "2026-09-17T06:59:16" sat_cert_number: type: string description: SAT certificate serial number used for stamping. @@ -13204,6 +13527,11 @@ components: LineItem: type: object properties: + property_tax_account: + type: array + items: + type: string + description: Property tax accounts for this line item. quantity: type: number description: Quantity of units included in the same concept. @@ -13217,7 +13545,9 @@ components: description: | Object with information about the product or service invoiced. parts: - $ref: "#/components/schemas/Parts" + type: array + items: + $ref: "#/components/schemas/Parts" description: Object with information about the parts conforming this item or product. ThirdParty: type: object @@ -13542,6 +13872,9 @@ components: CustomComplementProperties: title: CustomComplement type: object + required: + - type + - data properties: type: type: string @@ -13551,25 +13884,23 @@ components: data: $ref: '#/components/schemas/CustomComplementData' CustomComplementInput: + required: + - type + - data title: CustomComplement allOf: - - type: object - required: - - type - - data - $ref: "#/components/schemas/CustomComplementProperties" NominaComplementDataInput: + required: + - fecha_inicial_pago + - fecha_final_pago + - num_dias_pagados + - receptor + - percepciones title: NominaComplementData description: | Object with the information of the payroll complement. allOf: - - type: object - required: - - fecha_inicial_pago - - fecha_final_pago - - num_dias_pagados - - receptor - - percepciones - $ref: "#/components/schemas/NominaComplementDataDirectProperties" - $ref: "#/components/schemas/NominaComplementDataNestedInput" NominaComplementDataProperties: @@ -13591,17 +13922,16 @@ components: - `"O"` (Ordinary): For payments made in a regular manner, such as salaries. - `"E"` (Extraordinary): For payments outside the ordinary, such as settlements, bonuses, or Christmas bonuses. fecha_pago: - type: string - format: date - default: now - description: Payment date of the payroll to the worker. + allOf: + - $ref: "#/components/schemas/DateOrDateTime" + description: "Date the employee was paid. If omitted, the current date and time are used." fecha_inicial_pago: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: Initial date of the payment period. fecha_final_pago: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: Final date of the payment period. num_dias_pagados: type: number @@ -13611,7 +13941,7 @@ components: type: object properties: emisor: - $ref: "#/components/schemas/NominaEmisorProperties" + $ref: "#/components/schemas/NominaEmisorInput" receptor: $ref: "#/components/schemas/NominaReceptorInput" percepciones: @@ -13668,12 +13998,11 @@ components: $ref: "#/components/schemas/NominaIncapacidadProperties" NominaIncapacidadInput: + required: + - dias_incapacidad + - tipo_incapacidad title: Incapacidad allOf: - - type: object - required: - - dias_incapacidad - - tipo_incapacidad - $ref: "#/components/schemas/NominaIncapacidadProperties" NominaIncapacidadProperties: type: object @@ -13689,13 +14018,12 @@ components: type: number description: Monetary amount of the paid incapacity. NominaOtroPagoInput: + required: + - tipo_otro_pago + - clave + - importe title: OtroPago allOf: - - type: object - required: - - tipo_otro_pago - - clave - - importe - $ref: "#/components/schemas/NominaOtroPagoDirectProperties" - type: object properties: @@ -13727,12 +14055,11 @@ components: This value will be inserted within the `SubsidioAlEmpleo` node, and is required when the value of `tipo_otro_pago` is `"002"`. NominaCompensacionInput: + required: + - saldo_a_favor + - ano + - remanente_sal_fav allOf: - - type: object - required: - - saldo_a_favor - - ano - - remanente_sal_fav - $ref: "#/components/schemas/NominaCompensacionProperties" NominaCompensacionProperties: type: object @@ -13748,13 +14075,12 @@ components: type: number description: Remaining balance in favor of the worker. NominaDeduccionInput: + required: + - tipo_deduccion + - clave + - importe title: Deduccion allOf: - - type: object - required: - - tipo_deduccion - - clave - - importe - $ref: "#/components/schemas/NominaDeduccionProperties" NominaDeduccionProperties: type: object @@ -13804,15 +14130,14 @@ components: separacion_indemnizacion: $ref: "#/components/schemas/NominaSeparacionProperties" NominaSeparacionInput: + required: + - total_pagado + - num_anos_servicio + - ultimo_sueldo_mens_ord + - ingreso_acumulable + - ingreso_no_acumulable title: Separacion allOf: - - type: object - required: - - total_pagado - - num_anos_servicio - - ultimo_sueldo_mens_ord - - ingreso_acumulable - - ingreso_no_acumulable - $ref: "#/components/schemas/NominaSeparacionProperties" NominaSeparacionProperties: type: object @@ -13835,12 +14160,11 @@ components: type: number description: Amount for non-accumulable income. NominaJubilacionInput: + required: + - ingreso_acumulable + - ingreso_no_acumulable title: Jubilacion allOf: - - type: object - required: - - ingreso_acumulable - - ingreso_no_acumulable - $ref: "#/components/schemas/NominaJubilacionProperties" NominaJubilacionProperties: type: object @@ -13867,16 +14191,79 @@ components: - $ref: "#/components/schemas/NominaPercepcionDirectProperties" - $ref: "#/components/schemas/NominaPercepcionNestedProperties" NominaPercepcionInput: + required: + - tipo_percepcion + - clave + - importe_gravado + - importe_exento + description: "Input uses the perception codes in the published catalog. Code 019 requires horas_extra." title: Percepcion allOf: - - type: object - required: - - tipo_percepcion - - clave - - importe_gravado - - importe_exento - $ref: "#/components/schemas/NominaPercepcionDirectProperties" - $ref: "#/components/schemas/NominaPercepcionNestedInput" + oneOf: + - type: object + properties: + tipo_percepcion: + type: string + const: "019" + horas_extra: + type: array + items: + $ref: "#/components/schemas/NominaHorasExtraInput" + required: + - horas_extra + - type: object + properties: + tipo_percepcion: + type: string + enum: + - "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: type: object properties: @@ -13918,14 +14305,13 @@ components: items: $ref: "#/components/schemas/NominaHorasExtraProperties" NominaHorasExtraInput: + required: + - dias + - tipo_horas + - horas_extra + - importe_pagado title: HorasExtra allOf: - - type: object - required: - - dias - - tipo_horas - - horas_extra - - importe_pagado - $ref: "#/components/schemas/NominaHorasExtraProperties" NominaHorasExtraProperties: type: object @@ -13944,12 +14330,11 @@ components: type: number description: Amount paid for extra hours. NominaAccionesInput: + required: + - valor_mercado + - precio_al_otorgarse title: Accion allOf: - - type: object - required: - - valor_mercado - - precio_al_otorgarse - $ref: "#/components/schemas/NominaAccionesProperties" NominaAccionesProperties: type: object @@ -13970,18 +14355,17 @@ components: - $ref: "#/components/schemas/NominaReceptorDirectProperties" - $ref: "#/components/schemas/NominaReceptorNestedProperties" NominaReceptorInput: + required: + - curp + - tipo_contrato + - tipo_regimen + - num_empleado + - periodicidad_pago + - clave_ent_fed type: object title: Receptor description: Worker information. allOf: - - type: object - required: - - curp - - tipo_contrato - - tipo_regimen - - num_empleado - - periodicidad_pago - - clave_ent_fed - $ref: "#/components/schemas/NominaReceptorDirectProperties" - $ref: "#/components/schemas/NominaReceptorNestedInput" NominaReceptorDirectProperties: @@ -13994,8 +14378,8 @@ components: type: string description: Social security number. fecha_inicio_rel_laboral: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: | Start date of the employment relationship between the employer and the employee. @@ -14092,6 +14476,38 @@ components: minimum: 0.001 maximum: 100.000 description: Percentage of time the worker provided their services to the person or company that subcontracted them. + NominaEntidadSncfInput: + type: object + required: + - origen_recurso + properties: + origen_recurso: + type: string + enum: [IP, IF, IM] + monto_recurso_propio: + type: number + oneOf: + - type: object + properties: + origen_recurso: + type: string + const: IM + monto_recurso_propio: + type: number + required: + - monto_recurso_propio + - type: object + properties: + origen_recurso: + type: string + enum: [IP, IF] + NominaEmisorInput: + allOf: + - $ref: "#/components/schemas/NominaEmisorProperties" + - type: object + properties: + entidad_sncf: + $ref: "#/components/schemas/NominaEntidadSncfInput" NominaEmisorProperties: type: object title: Emisor @@ -14122,7 +14538,7 @@ components: - IM description: | Key of the origin of the resource. - + - `“IP”`: Ingresos Propios (Own income) - `“IF”`: Ingresos Federales (Federal income) - `“IM”`: Ingresos mixtos (Mixed income) @@ -14147,6 +14563,10 @@ components: - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/PagoComplementProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + PagoOrCustomComplementInput: type: object title: Complement @@ -14162,30 +14582,99 @@ components: type: type: string enum: - - nomina + - pago - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/PagoComplementInput" + - $ref: "#/components/schemas/CustomComplementInput" + PagoComplementProperties: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: pago - type: object properties: data: - $ref: "#/components/schemas/NominaComplementDataProperties" + $ref: "#/components/schemas/PagoComplementDataProperties" PagoComplementInput: allOf: - - $ref: "#/components/schemas/PagoOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: pago - type: object properties: data: $ref: "#/components/schemas/PagoComplementDataInput" - PagoComplementDataInput: + InvoiceComplementInput: + oneOf: + - $ref: "#/components/schemas/PagoComplementInput" + - $ref: "#/components/schemas/NominaComplementInput" + - $ref: "#/components/schemas/CartaPorteInput" + - $ref: "#/components/schemas/ComercioExteriorInput" + - $ref: "#/components/schemas/LeyendasFiscalesInput" + - $ref: "#/components/schemas/CustomComplementInput" + discriminator: + propertyName: type + mapping: + pago: "#/components/schemas/PagoComplementInput" + nomina: "#/components/schemas/NominaComplementInput" + carta_porte: "#/components/schemas/CartaPorteInput" + comercio_exterior: "#/components/schemas/ComercioExteriorInput" + leyendas_fiscales: "#/components/schemas/LeyendasFiscalesInput" + custom: "#/components/schemas/CustomComplementInput" + InvoiceComplementProperties: + oneOf: + - $ref: '#/components/schemas/PagoComplementProperties' + - $ref: '#/components/schemas/NominaComplementProperties' + - $ref: '#/components/schemas/CartaPorteProperties' + - $ref: '#/components/schemas/ComercioExteriorProperties' + - $ref: '#/components/schemas/LeyendasFiscalesProperties' + - $ref: '#/components/schemas/CustomComplementProperties' + discriminator: + propertyName: type + mapping: + pago: '#/components/schemas/PagoComplementProperties' + nomina: '#/components/schemas/NominaComplementProperties' + carta_porte: '#/components/schemas/CartaPorteProperties' + comercio_exterior: '#/components/schemas/ComercioExteriorProperties' + leyendas_fiscales: '#/components/schemas/LeyendasFiscalesProperties' + custom: '#/components/schemas/CustomComplementProperties' + PagoComplementDataProperties: type: array - title: PagoComplementData - description: Payments to include in this document. The most common is to include only one payment. A case in which more than one must be added is when the payment is made with 2 different payment methods; for example, when one part is paid by card and the other in cash. items: - $ref: "#/components/schemas/PaymentInput" + $ref: '#/components/schemas/PaymentProperties' + PaymentProperties: + allOf: + - $ref: '#/components/schemas/PaymentInput' + - type: object + required: + - date + properties: + date: + type: string + format: date-time + PagoComplementDataInput: + title: PagoComplementData + description: Payments to include in this document. The most common is to include only one payment. A case in which more than one must be added is when the payment is made with 2 different payment methods; for example, when one part is paid by card and the other in cash. + oneOf: + - $ref: "#/components/schemas/PaymentInput" + - type: array + minItems: 1 + items: + $ref: "#/components/schemas/PaymentInput" NominaOrCustomComplementProperties: title: Complement type: object @@ -14202,6 +14691,10 @@ components: - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/NominaComplementProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + NominaOrCustomComplementInput: type: object title: Complement @@ -14220,16 +14713,34 @@ components: - nomina - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/NominaComplementInput" + - $ref: "#/components/schemas/CustomComplementInput" + NominaComplementProperties: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: nomina - type: object properties: data: $ref: "#/components/schemas/NominaComplementDataProperties" NominaComplementInput: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: nomina - type: object properties: data: @@ -14237,42 +14748,84 @@ components: # Carta Porte Complement CartaPorteProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: carta_porte - type: object properties: data: $ref: "#/components/schemas/CartaPorteDataProperties" CartaPorteInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: carta_porte - type: object properties: data: $ref: "#/components/schemas/CartaPorteDataInput" ComercioExteriorProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: comercio_exterior - type: object properties: data: $ref: "#/components/schemas/ComercioExteriorDataProperties" ComercioExteriorInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: comercio_exterior - type: object properties: data: $ref: "#/components/schemas/ComercioExteriorDataInput" LeyendasFiscalesProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: leyendas_fiscales - type: object properties: data: $ref: "#/components/schemas/LeyendasFiscalesData" LeyendasFiscalesInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: leyendas_fiscales - type: object properties: data: @@ -14296,6 +14849,12 @@ components: - leyendas_fiscales - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/CartaPorteProperties" + - $ref: "#/components/schemas/ComercioExteriorProperties" + - $ref: "#/components/schemas/LeyendasFiscalesProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + CartaPorteOrCustomComplementInput: title: Complement type: object @@ -14318,6 +14877,12 @@ components: - leyendas_fiscales - custom description: Type of complement + oneOf: + - $ref: "#/components/schemas/CartaPorteInput" + - $ref: "#/components/schemas/ComercioExteriorInput" + - $ref: "#/components/schemas/LeyendasFiscalesInput" + - $ref: "#/components/schemas/CustomComplementInput" + LeyendasFiscalesData: type: object title: LeyendasFiscales @@ -14906,6 +15471,11 @@ components: $ref: "#/components/schemas/CartaPorteDetalleMercancia" CartaPorteIdentificacionVehicular: type: object + required: + - ConfigVehicular + - PesoBrutoVehicular + - PlacaVM + - AnioModeloVM properties: ConfigVehicular: type: string @@ -14921,6 +15491,9 @@ components: description: Model year of the motor vehicle. CartaPorteSeguros: type: object + required: + - AseguraRespCivil + - PolizaRespCivil properties: AseguraRespCivil: type: string @@ -14954,6 +15527,11 @@ components: description: Trailer license plate. CartaPorteAutotransporte: type: object + required: + - PermSCT + - NumPermisoSCT + - IdentificacionVehicular + - Seguros properties: PermSCT: type: string @@ -15291,11 +15869,11 @@ components: exterior: type: string description: Exterior number. - example: 142 + example: "142" interior: type: string description: Interior number. - example: 4 + example: "4" neighborhood: type: string description: Neighborhood @@ -15311,7 +15889,7 @@ components: zip: type: string description: Postal code - example: 86500 + example: "86500" # Main resources Webhook: title: Webhook object @@ -15322,6 +15900,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -15334,16 +15914,29 @@ components: description: | ID of the organization for which the webhook is being created. livemode: - type: boolean + type: boolean example: false description: Environment in which the webhook is being created. enabled_events: - type: string - example: ["receipt.cancellation_status"] - description: Events enabled for the webhook to listen to. + type: array + example: + - receipt.status_updated + description: | + Subscribed webhook events. Existing responses may contain "*", but creating or updating a webhook requires explicit event names; the wildcard is not accepted in requests. + items: + type: string + enum: + - 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 + - "*" url: type: string - format: email + format: uri description: Full URL of the webhook listener. example: http://my-website.com/my/webhook status: @@ -15353,6 +15946,13 @@ components: - enabled - disabled example: enabled + secret: + type: string + readOnly: true + description: Secret for verifying signatures. Returned when creating the webhook. + description: + type: string + type: object WebhookCreateInput: title: Webhook allOf: @@ -15365,76 +15965,98 @@ components: type: string description: Full URL of the webhook listener. example: http://webhook_api.com + format: uri enabled_events: type: array items: type: string - enum: - - "invoice.global_invoice_created" - - "invoice.status_updated" - - "invoice.cancellation_status_updated" - - "invoice.created_from_dashboard" - - "receipt.self_invoice_complete" - - "receipt.status_updated" - - "receipt.cancellation_status_updated" + enum: + - 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 description: Events enabled for the webhook to listen to. - example: ["receipt.self_invoice_complete"] + example: + - receipt.self_invoice_complete + minItems: 1 WebhookCreateEdit: title: Webhook allOf: - type: object required: - enabled_events + - status properties: status: type: string description: Status of the webhook. enum: - - "disabled" - - "enabled" + - disabled + - enabled example: disabled enabled_events: type: array items: type: string - enum: - - "invoice.global_invoice_created" - - "invoice.status_updated" - - "invoice.cancellation_status_updated" - - "receipt.self_invoice_complete" - - "receipt.status_updated" - - "receipt.cancellation_status_updated" - description: Events enabled for the webhook to listen to. - example: ["receipt.self_invoice_complete"] + enum: + - 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 + description: Events enabled for the webhook to listen to. + example: + - receipt.self_invoice_complete + minItems: 1 Customer: title: Customer object allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/CustomerNonEditableProperties" - - $ref: "#/components/schemas/CustomerProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/CustomerNonEditableProperties' + - $ref: '#/components/schemas/CustomerProperties' + - type: object + properties: + organization: + description: "ID of the organization this resource belongs to." + type: string + curp: + type: string + external_id: + type: string CustomerNonEditableProperties: type: object properties: edit_link: - type: string + type: + - string + - 'null' description: Link to a hosted page where the customer can edit their information once. example: https://auto.facturapi.io/tax-info/abcdWXYZ1234 edit_link_expires_at: - type: string + type: + - string + - 'null' format: date-time description: Expiration date of the edit link. - example: 2022-12-31T23:59:59Z + example: '2022-12-31T23:59:59Z' sat_validated_at: - type: string + type: [string, "null"] format: date-time description: Date when the customer's tax information was validated by the SAT. - example: 2022-12-31T23:59:59Z + example: '2022-12-31T23:59:59Z' CustomerSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -15468,65 +16090,231 @@ components: description: | Legal name or business name of the customer. *without* the corporate regime (e.g.: S.A. de C.V.). example: Dunder Mifflin - tax_id: - type: string - example: ABC101010111 - description: | - In Mexican clients, it contains the customer's RFC. For foreigners, it is optional and represents the tax identification number, that is, the equivalent to the RFC in the customer's country. - tax_system: - type: string - example: "601" - maxLength: 3 - minLength: 3 - description: | - Required for national clients. Key of the customer's tax regime, from the [Tax Regime Catalog](#tax-regime). + tax_id: + type: + - string + - 'null' + example: ABC101010111 + description: | + In Mexican clients, it contains the customer's RFC. For foreigners, it is optional and represents the tax identification number, that is, the equivalent to the RFC in the customer's country. + tax_system: + type: + - string + - 'null' + example: '601' + maxLength: 3 + minLength: 3 + description: | + Required for national clients. Key of the customer's tax regime, from the [Tax Regime Catalog](#tax-regime). + email: + type: string + format: email + description: Email address to which to send the generated invoices. + example: email@example.com + phone: + type: + - string + - 'null' + description: Customer's phone number. + example: '6474010101' + default_invoice_use: + type: string + description: Default CFDI use for the customer. + example: G01 + CancellationQueryInput: + description: Omit query parameters to delete a draft. Issued documents require a motive; motives 01 and 04 also require substitution. + anyOf: + - title: Replacement required + type: object + required: + - motive + - substitution + properties: + motive: + type: string + enum: + - '01' + - '04' + substitution: + type: string + description: Facturapi ID or UUID of the replacement document. + - title: Other cancellation motives + type: object + required: + - motive + properties: + motive: + type: string + enum: + - '02' + - '03' + substitution: + type: string + - title: Delete draft + type: object + properties: + motive: false + substitution: false + CustomerCreateWithEditLinkInput: + title: Customer with edit link + description: Customer information may be incomplete when createEditLink=true. Supplied fields must still have valid formats. + allOf: + - $ref: '#/components/schemas/CustomerProperties' + - type: object + properties: + tax_system: + type: string + description: If supplied, use a valid fiscal regime. Omission permits incomplete fiscal information. + CustomerCreateCommonInput: + type: object + required: + - legal_name + properties: + legal_name: + type: string + description: | + Legal name or business name of the customer. *without* the corporate regime (e.g.: S.A. de C.V.). + example: Dunder Mifflin email: type: string format: email description: Email address to which to send the generated invoices. example: email@example.com phone: - type: string + type: + - string + - 'null' description: Customer's phone number. - example: 6474010101 + example: '6474010101' default_invoice_use: type: string description: Default CFDI use for the customer. example: G01 - CustomerCreateInput: - title: Customer + CustomerNationalAddressInput: allOf: - - $ref: "#/components/schemas/CustomerCommonProperties" + - $ref: '#/components/schemas/CommonAddressProperties' + - type: object + properties: + state: + type: string + country: + type: string + const: MEX + default: MEX + required: + - zip + CustomerForeignAddressInput: + allOf: + - $ref: '#/components/schemas/CommonAddressProperties' + - type: object + required: + - country + properties: + country: + type: string + not: + const: MEX + minLength: 3 + maxLength: 3 + description: ISO 3166-1 alpha-3 country code other than MEX. Required to select foreign customer rules. + state: + type: string + CustomerNationalCreateInput: + title: Mexican customer + description: Country MEX, or omitted. Fiscal name, RFC, fiscal regime and postal code are required. Generic RFCs use CustomerGenericCreateInput. + allOf: + - $ref: '#/components/schemas/CustomerCreateCommonInput' - type: object required: - - legal_name - - tax_id - - tax_system - - address + - tax_id + - tax_system + - address properties: + tax_id: + type: string + example: ABC101010111 + description: | + In Mexican clients, it contains the customer's RFC. For foreigners, it is optional and represents the tax identification number, that is, the equivalent to the RFC in the customer's country. + not: + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: string + example: '601' + maxLength: 3 + minLength: 3 + description: | + Required for national clients. Key of the customer's tax regime, from the [Tax Regime Catalog](#tax-regime). address: - allOf: - - $ref: "#/components/schemas/CommonAddressProperties" - - type: object - description: Fiscal address. - required: - - zip - properties: - state: - type: string - description: If the country is Mexico ("MEX"), it contains the name of the State or Federative Entity. For foreigners, it contains the State code according to the standard [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2), which you can consult in our [State Catalog](https://dashboard.facturapi.io/catalogs/state). - example: Sonora - country: - type: string - description: Country code according to the standard [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3), from the [Country Catalog](https://dashboard.facturapi.io/catalogs/country). - example: MEX - default: MEX + $ref: '#/components/schemas/CustomerNationalAddressInput' + CustomerForeignCreateInput: + title: Foreign customer + description: Requires fiscal name and an address with an explicit country other than MEX. Tax ID and postal code are optional; the fiscal regime defaults to 616. + allOf: + - $ref: '#/components/schemas/CustomerCreateCommonInput' + - type: object + required: + - address + properties: + tax_id: + type: + - string + - 'null' + description: | + In Mexican clients, it contains the customer's RFC. For foreigners, it is optional and represents the tax identification number, that is, the equivalent to the RFC in the customer's country. + not: + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: + - string + - 'null' + enum: + - '616' + - null + - '' + default: '616' + description: Foreign customers use 616. Omission, null or an empty string use the default. + address: + $ref: '#/components/schemas/CustomerForeignAddressInput' + CustomerGenericCreateInput: + title: Generic RFC + description: Public general RFC XAXX010101000 or generic foreign RFC XEXX010101000. Fiscal name and RFC are required. The fiscal regime defaults to 616. If a Mexican address is supplied, a postal code is required. + allOf: + - $ref: '#/components/schemas/CustomerCreateCommonInput' + - type: object + required: + - tax_id + properties: + tax_id: + type: string + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: string + enum: + - '616' + default: '616' + address: + anyOf: + - $ref: '#/components/schemas/CustomerNationalAddressInput' + - $ref: '#/components/schemas/CustomerForeignAddressInput' + CustomerCreateInput: + title: Customer + description: Required fields depend on country and RFC. Omitted country means Mexico. With createEditLink=true, use CustomerCreateWithEditLinkInput instead. + anyOf: + - $ref: '#/components/schemas/CustomerNationalCreateInput' + - $ref: '#/components/schemas/CustomerForeignCreateInput' + - $ref: '#/components/schemas/CustomerGenericCreateInput' LineItemProductInput: title: Product allOf: - $ref: "#/components/schemas/ProductProperties" - + LineItemProductEgresoInput: title: Product allOf: @@ -15545,7 +16333,7 @@ components: product_key: type: string description: Key from the SAT catalog of products/services. We provide a more convenient way to find it using our [key search tool](https://dashboard.facturapi.io/catalogs/productKey). - example: 60131324 + example: "60131324" unit_key: type: string default: H87 @@ -15599,33 +16387,41 @@ components: type: string description: Customs entry number (pedimento aduanal) associated with this part. PartInput: + required: + - description + - product_key allOf: - - type: object - required: - - description - - product_key - $ref: "#/components/schemas/Parts" Product: title: Product object allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/ProductProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/ProductProperties' + - type: object + properties: + organization: + description: "ID of the organization this resource belongs to." + type: string + required: + - organization + - unit_key ProductSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array items: $ref: "#/components/schemas/Product" ProductProperties: + allOf: + - $ref: "#/components/schemas/ProductEditableProperties" + required: [description, product_key, price] + ProductEditableProperties: type: object - required: - - description - - product_key - - unit_key - - price properties: description: type: string @@ -15634,7 +16430,7 @@ components: product_key: type: string description: Key from the SAT catalog of products/services. We provide a more convenient way to find it using our [key search tool](https://dashboard.facturapi.io/catalogs/productKey). - example: 60131324 + example: "60131324" price: type: number description: | @@ -15725,11 +16521,11 @@ components: example: Ukelele product_key: type: string - default: 84111506 + default: "84111506" description: | Key from the SAT catalog of products/services. We provide a more convenient way to find it using our [key search tool](https://dashboard.facturapi.io/catalogs/productKey). - example: 84111506 + example: "84111506" price: type: number description: | @@ -15883,22 +16679,16 @@ components: description: Indicates if the tax is a withholding (`true`) or a transfer (`false`). taxability: type: string - default: | - "01" if the `taxes` array is empty; "02" if the `taxes` array has at least one element. enum: - "01" - "02" - "03" - "04" - "05" - description: | - Code representing whether the good or service is subject to tax or not. This attribute corresponds to the "ObjetoImp" field in the CFDI. - - - `01`: Not subject to tax. - - `02`: Subject to tax. - - `03`: Subject to tax, but not required to break down. - - `04`: Subject to tax, but does not cause tax. - - `05`: Subject to tax, VAT credit PODEBI. + - "06" + - "07" + - "08" + description: "Code representing whether the good or service is subject to tax or not. This attribute corresponds to the \"ObjetoImp\" field in the CFDI.\n\n- `01`: Not subject to tax.\n- `02`: Subject to tax.\n- `03`: Subject to tax, but not required to break down.\n- `04`: Subject to tax, but does not cause tax.\n- `05`: Subject to tax, VAT credit PODEBI.\n- `06`: Taxable, without transferred VAT.\n- `07`: No transferred VAT, with an IEPS breakdown.\n- `08`: No transferred VAT, without an IEPS breakdown.\n\nIf omitted, `01` is used when `taxes` is empty and `02` when it contains at least one tax." installment: type: integer description: | @@ -15927,7 +16717,7 @@ components: description: | Optional. You can include the folio number of the related document. series: - type: string + type: [string, "null"] description: | Optional. You can include the series of the related document. currency: @@ -15947,8 +16737,7 @@ components: date: type: string format: date-time - default: now - description: Date on which the payment was received. It is only necessary to include it if the payment was made on a date prior to the issuance of this document. Future dates are not allowed. + description: "Date the payment was received. If omitted, the current date and time are used. Include it when payment occurred before this invoice was issued. Future dates are not allowed." numOperacion: type: string description: | @@ -15971,7 +16760,7 @@ components: tipoCadPago: type: string enum: - - 01 + - "01" description: | Key of the type of payment chain generated by the receiving entity of the payment. If this field exists, it is mandatory to register the `certPago`, `cadPago`, and `selloPago` fields. @@ -16014,9 +16803,14 @@ components: country: type: string format: ISO 3166-1 alpha-3 - # description: Código de País acorde al estándar ISO 3166-1 alpha-3, del Catálogo de Países. description: Country code according to the standard [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3). example: MEX + zip: + type: string + tax_system: + type: + - string + - 'null' CustomerComercioExterior: type: object description: 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'). @@ -16026,11 +16820,10 @@ components: description: ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado example: 58e93bd8e86eb318b0197456 RelatedDocumentInput: + required: + - relationship + - related allOf: - - type: object - required: - - relationship - - related - $ref: '#/components/schemas/RelatedDocument' RelatedDocument: type: object @@ -16063,11 +16856,11 @@ components: InvoiceZipRequestInvoiceType: type: string enum: - - I - - E - - T - - N - - P + - "I" + - "E" + - "T" + - "N" + - "P" description: Invoice type (`I` Income, `E` Credit note/expense, `T` Transport, `N` Payroll, or `P` Payment). InvoiceZipRequestCreateInput: type: object @@ -16102,7 +16895,7 @@ components: InvoiceZipRequest: title: InvoiceZipRequest object allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' - type: object required: - organization @@ -16125,13 +16918,13 @@ components: description: Organization identifier. example: 65a1f0000000000000000000 issuer_type: - $ref: "#/components/schemas/IssuingType" + $ref: '#/components/schemas/IssuingType' invoice_types: type: array description: Normalized invoice types included in the request. uniqueItems: true items: - $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" + $ref: '#/components/schemas/InvoiceZipRequestInvoiceType' example: - E - I @@ -16139,14 +16932,14 @@ components: type: string format: date-time description: Inclusive start of the requested month. - example: "2025-03-01T06:00:00.000Z" + example: '2025-03-01T06:00:00.000Z' end_date: type: string format: date-time description: Inclusive end of the requested month. - example: "2025-04-01T04:59:59.999Z" + example: '2025-04-01T04:59:59.999Z' status: - $ref: "#/components/schemas/InvoiceZipRequestStatus" + $ref: '#/components/schemas/InvoiceZipRequestStatus' document_count: type: integer minimum: 0 @@ -16167,7 +16960,11 @@ components: type: string format: date-time description: Date when processing was scheduled. - example: "2026-08-04T18:00:01.000Z" + example: '2026-08-04T18:00:01.000Z' + processing_started_at: + type: string + format: date-time + description: Time processing started, when present. InvoiceZipRequestSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" @@ -16196,6 +16993,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -16209,6 +17008,8 @@ components: - price InvoiceProperties: type: object + required: + - date properties: status: type: string @@ -16234,7 +17035,9 @@ components: Current status of the cancellation request, if it has been made. `verifying` means the SAT has received the request and is validating it; Facturapi will keep checking until it changes to a final status. You can read more in the [Cancel Invoice](#tag/invoice/operation/deleteInvoice) section. example: none canceled_at: - type: string + type: + - string + - 'null' format: date-time description: Date on which CFDI was canceled, with approximate time. verification_url: @@ -16243,14 +17046,14 @@ components: description: URL to verify the status of the CFDI on the SAT portal. This link is the same as the one that appears in the QR code on the invoice PDF. example: https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=45BEC0CA-5F1E-491E-9417-698EA48C382A&re=AAA010101AAA&rr=ABC101010111&tt=345.600000&fe=bWApPw== date: - type: string + type: + - string + - 'null' format: date-time - default: now - description: | - Date of issuance of the invoice in ISO8601 format (UTC String). + description: Issue date in ISO8601 format. May be null for drafts. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: '#/components/schemas/CommonAddressProperties' - type: object description: Address where the invoice was issued. properties: @@ -16261,15 +17064,17 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. customer: - $ref: "#/components/schemas/CustomerInfo" + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' total: type: number description: Total amount invoiced. @@ -16296,7 +17101,7 @@ components: payment_form: type: string description: Payment form code according to the [Payment Form catalog](#payment-form). - example: 06 + example: "06" total_payment_amount: type: number description: Total amount of the Payment complement when the invoice is type P. @@ -16311,21 +17116,21 @@ components: try to stamp the invoice with the [Stamp Invoice]('#/operation/stampInvoice') method. If the value is `false`, you must use the [Update Invoice]('#/operation/updateDraftInvoice') method to complete the missing fields. - + In an invoice with a status other than `draft`, this field will always be `false`. items: type: array description: Concepts included in the document. items: - $ref: "#/components/schemas/LineItem" + $ref: '#/components/schemas/LineItem' related_documents: type: array description: Documents related to the invoice. items: - $ref: "#/components/schemas/RelatedDocument" + $ref: '#/components/schemas/RelatedDocument' received_payment_ids: type: array - items: + items: type: string description: | On invoices with type I (Income) and payment method PPD, this field lists the @@ -16355,7 +17160,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + $ref: '#/components/schemas/InvoiceComplementProperties' description: Complements to include in the invoice. pdf_custom_section: type: string @@ -16369,9 +17174,58 @@ components: type: array description: Namespaces to insert in the root node of the invoice. Required for `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' stamp: - $ref: "#/components/schemas/Stamp" + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' + organization: + description: "ID of the organization this resource belongs to." + type: + - string + - 'null' + issuer_type: + $ref: '#/components/schemas/IssuingType' + cfdi_version: + type: number + example: 4 + issuer_info: + $ref: '#/components/schemas/CustomerInfo' + payment_method: + type: string + enum: + - PUE + - PPD + use: + type: string + amount_due: + type: number + verification_carta_porte: + type: string + format: uri + conditions: + type: string + export: + type: string + global: + type: object + required: + - periodicity + - months + - year + properties: + periodicity: + type: string + enum: + - day + - week + - fortnight + - month + - two_months + months: + type: string + year: + type: integer InvoiceDraftProperties: type: object properties: @@ -16401,16 +17255,17 @@ components: type: string format: uri description: URL to verify the status of the CFDI on the SAT portal. This link is the same as the one that appears in the QR code on the invoice PDF. - example: null date: - type: string + type: + - string + - 'null' format: date-time example: null description: | Date of issuance of the invoice in ISO8601 format (UTC String). If the status is `draft`, this field is null. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: '#/components/schemas/CommonAddressProperties' - type: object description: Address where the invoice was issued. properties: @@ -16421,24 +17276,26 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. customer: - $ref: "#/components/schemas/CustomerInfo" + description: Invoice customer. Null when the draft has no customer. + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' total: type: number description: Total amount invoiced. example: 0 uuid: - type: string + type: [string, "null"] format: uuid - description: Fiscal folio of the invoice, assigned by the SAT. If the invoice has not been stamped, this field is null. - example: 0 + description: Fiscal folio assigned by the SAT. For an unstamped draft, this field is null or omitted. folio_number: type: integer description: Autoincremental folio number for internal control and without fiscal relevance. @@ -16456,17 +17313,17 @@ components: payment_form: type: string description: Payment form code according to the [Payment Form catalog](#forma-de-pago). - example: 06 + example: "06" items: type: array description: Concepts included in the document. items: - $ref: "#/components/schemas/LineItem" + $ref: '#/components/schemas/LineItem' related_documents: type: array description: Documents related to the invoice. items: - $ref: "#/components/schemas/RelatedDocument" + $ref: '#/components/schemas/RelatedDocument' currency: type: string example: MXN @@ -16480,7 +17337,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + $ref: '#/components/schemas/InvoiceComplementProperties' description: Complements to include in the invoice. pdf_custom_section: type: string @@ -16494,7 +17351,7 @@ components: type: array description: Namespaces to insert in the root node of the invoice. Required for `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' is_ready_to_stamp: type: boolean description: | @@ -16506,17 +17363,16 @@ components: In an invoice with a status other than `draft`, this field will always be `false`. stamp: - allOf: - - $ref: "#/components/schemas/Stamp" - - type: object - example: null + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' + example: null InvoiceableCommonInput: type: object properties: folio_number: type: integer - default: autoincremental description: | Number of folio assigned by the company for internal control. If omitted, the autoincremental value of the organization will be assigned. series: @@ -16743,18 +17599,20 @@ components: antiguedad: type: boolean default: false + InvoiceCustomerInput: + description: Customer receiving the invoice. + oneOf: + - $ref: "#/components/schemas/CustomerCreateInput" + - type: string + title: customer_id + description: ID of the `customer` object previously registered in Facturapi. + example: 58e93bd8e86eb318b0197456 InvoiceCommonInputProperties: allOf: - type: object properties: customer: - description: Customer receiving the invoice. - oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" - - type: string - title: customer_id - description: ID of the `customer` object previously registered in Facturapi. - example: 58e93bd8e86eb318b0197456 + $ref: "#/components/schemas/InvoiceCustomerInput" status: type: string enum: @@ -16763,7 +17621,7 @@ components: default: pending description: | Initial status of the invoice. - + If `draft` is sent, the invoice will be saved as a draft and will not be stamped or sent to the SAT. Also, when sending `draft`, all required fields become optional. @@ -16776,9 +17634,7 @@ components: date: type: string format: date-time - default: now - description: | - Date of issuance of the invoice in ISO8601 format (UTC String). It cannot be earlier than 72 hours in the past, nor later than the present. + description: "Invoice issuance date in ISO8601 format. If omitted, the current date and time are used. It cannot be more than 72 hours in the past or in the future." address: allOf: - $ref: "#/components/schemas/CommonAddressProperties" @@ -16808,21 +17664,13 @@ components: allOf: - type: object properties: - customer: - description: Customer receiving the invoice. - oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" - - type: string - title: customer_id - description: ID of the `Customer` object previously registered in Facturapi. - example: 58e93bd8e86eb318b0197456 status: type: string enum: - draft description: | - Initial status of the invoice. It is only possible to edit an invoice with status `draft`, - and it is not possible to change the status when editing, so the only allowed value is `draft`. + Invoice status. The value `draft` identifies a draft that has not been stamped or sent to SAT. + Only invoices with this status can be edited; `status` cannot be changed while editing. example: draft date: type: string @@ -16831,69 +17679,175 @@ components: Date of issuance of the invoice in ISO8601 format (UTC String). It cannot be earlier than 72 hours in the past, nor later than the present. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: "#/components/schemas/CommonAddressProperties" + - type: object + description: | + You can use this parameter to specify the address where the invoice was issued. + This field is optional and if not sent, the invoice will be issued with the address of the organization. + required: + - zip + properties: + state: + type: string + description: If the country is Mexico ("MEX"), this field should contain the name of the State or Federative Entity. For foreigners, it should contain the State code according to the standard [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2), which you can consult in our [State Catalog](https://dashboard.facturapi.io/catalogs/state). + example: Sonora + external_id: + type: string + description: | + Optional identifier that you can use to relate this invoice to your records and later search by this number. Facturapi does not validate that this field is unique. + idempotency_key: + type: string + description: | + Unique identifier that you can use to avoid duplicates when retrying a request. It can be any text string, as long as it is unique for each document. + + If left blank, it will not be taken into account. + - $ref: "#/components/schemas/InvoiceableCommonEditInput" + InvoiceDraftInputProperties: + allOf: + - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - type: object + properties: + customer: + description: Customer receiving the invoice. + oneOf: + - type: "null" + - $ref: "#/components/schemas/CustomerCreateInput" + - type: string + title: customer_id + description: ID of the `Customer` object previously registered in Facturapi. + example: 58e93bd8e86eb318b0197456 + InvoiceCreateInput: + type: object + description: Invoice data according to its type and initial status. Omit status to stamp; use draft to save a draft. + oneOf: + - title: Income + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceIngresoInput' + - type: object + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceIngresoEditInput' + - type: object + required: + - status + properties: + status: + type: string + const: draft + - title: Egress + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceEgresoInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceEgresoEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft + - title: Payment + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoicePagoInput' - type: object - description: | - You can use this parameter to specify the address where the invoice was issued. - This field is optional and if not sent, the invoice will be issued with the address of the organization. required: - - zip + - type properties: - state: + status: type: string - description: If the country is Mexico ("MEX"), this field should contain the name of the State or Federative Entity. For foreigners, it should contain the State code according to the standard [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2), which you can consult in our [State Catalog](https://dashboard.facturapi.io/catalogs/state). - example: Sonora - external_id: - type: string - description: | - Optional identifier that you can use to relate this invoice to your records and later search by this number. Facturapi does not validate that this field is unique. - idempotency_key: - type: string - description: | - Unique identifier that you can use to avoid duplicates when retrying a request. It can be any text string, as long as it is unique for each document. - - If left blank, it will not be taken into account. - - $ref: "#/components/schemas/InvoiceableCommonEditInput" - InvoiceCreateInput: - type: object - oneOf: - - title: Income - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceIngresoInput" - draft: "#/components/schemas/InvoiceIngresoEditInput" - - title: Egress - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceEgresoInput" - draft: "#/components/schemas/InvoiceEgresoEditInput" - - title: Payment - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoicePagoInput" - draft: "#/components/schemas/InvoicePagoEditInput" + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoicePagoEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft - title: Payroll - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceNominaInput" - draft: "#/components/schemas/InvoiceNominaEditInput" + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceNominaInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceNominaEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft - title: Transfer - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceTrasladoInput" - draft: "#/components/schemas/InvoiceTrasladoEditInput" + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceTrasladoInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceTrasladoEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft InvoiceIngresoInput: title: Income required: - customer - items - payment_form - - use allOf: - type: object properties: @@ -16932,11 +17886,12 @@ components: - `PUE`: Payment in One Installment (paid in full at the time of the transaction) - `PPD`: Payment in Installments or Deferred (partial or deferred payment) use: - type: string - default: G01 + type: [string, "null"] description: | + If omitted or null, the customer default is used, falling back to G03. For foreign customers or the general public, S01 is used. + Code of Use of CFDI according to the SAT catalog. You can see the codes in [this table](#uso-cfdi), or use the constants included in our libraries. - + For global invoices you must use the code `S01`. currency: type: string @@ -17015,7 +17970,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the invoice. You can include any complement in the invoice if you build the XML node of the complement yourself and use the `custom` type. @@ -17069,7 +18024,7 @@ components: $ref: "#/components/schemas/LineItemEgresoInput" use: type: string - default: G01 + default: G02 description: | Code of Use of CFDI according to the SAT catalog. You can see the codes in [this table](#uso-cfdi), or use the constants included in our libraries. currency: @@ -17087,7 +18042,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the credit note. You can include any complement in the credit note if you build the XML node of the complement yourself and use the `custom` type. @@ -17124,9 +18079,17 @@ components: - $ref: "#/components/schemas/ThirdParty" complements: type: array - default: [] + minItems: 1 + contains: + type: object + required: + - type + properties: + type: + type: string + const: pago items: - $ref: "#/components/schemas/PagoOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complements to include in the invoice. - $ref: "#/components/schemas/InvoiceCommonInputProperties" InvoiceNominaInput: @@ -17141,12 +18104,20 @@ components: type: type: string enum: - - N + - "N" complements: type: array - default: [] + minItems: 1 + contains: + type: object + required: + - type + properties: + type: + type: string + const: nomina items: - $ref: "#/components/schemas/NominaOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complements to include in the invoice. related_documents: type: array @@ -17182,7 +18153,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the invoice. You can include any complement in the invoice if you build the XML node of the complement yourself and use the `custom` type. @@ -17190,12 +18161,12 @@ components: `pdf_custom_section` parameter. use: type: string - default: G01 + default: S01 description: | Code of Use of CFDI according to the SAT catalog. You can see the codes in [this table](#uso-cfdi), or use the constants included in our libraries. currency: type: string - default: MXN + default: XXX description: Currency code, according to the standard [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). exchange: type: number @@ -17218,14 +18189,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. + const: "I" + description: "Document type for this input variant." items: type: array maxItems: 5000 @@ -17237,7 +18202,7 @@ components: items: $ref: "#/components/schemas/LineItemInput" payment_form: - type: string + type: [string, "null"] minLength: 2 maxLength: 2 example: "03" @@ -17253,11 +18218,11 @@ components: - `PUE`: Payment in One Installment (paid in full at the time of the transaction) - `PPD`: Payment in Installments or Deferred (partial or deferred payment) use: - type: string + type: [string, "null"] example: G01 description: | Code of Use of CFDI according to the SAT catalog. You can see the codes in [this table](#uso-cfdi), or use the constants included in our libraries. - + For global invoices you must use the code `S01`. currency: type: string @@ -17330,13 +18295,13 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the invoice. You can include any complement in the invoice if you build the XML node of the complement yourself and use the `custom` type. It is necessary to add the complement information to the PDF separately using the `pdf_custom_section` parameter. - - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoiceEgresoEditInput: title: Egress allOf: @@ -17344,14 +18309,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. + const: "E" + description: "Document type for this input variant." payment_form: type: string minLength: 2 @@ -17376,7 +18335,7 @@ components: maxItems: 5000 description: | Concepts to include in the credit note. - + The maximum number of elements that you can include in a document is 5,000. If you need to issue a document with more than 5,000 concepts, you can divide the transaction into several documents. items: @@ -17397,13 +18356,13 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the credit note. You can include any complement in the credit note if you build the XML node of the complement yourself and use the `custom` type. It is necessary to add the complement information to the PDF separately using the `pdf_custom_section` parameter. - - $ref: "#/components/schemas/InvoiceCommonInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoicePagoEditInput: title: Payment allOf: @@ -17411,14 +18370,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. + const: "P" + description: "Document type for this input variant." related_documents: type: array description: Documents related to the invoice. @@ -17436,28 +18389,24 @@ components: complements: type: array items: - $ref: "#/components/schemas/PagoOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complements to include in the invoice. - - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoiceNominaEditInput: title: Payroll allOf: - type: object properties: + customer: + $ref: "#/components/schemas/InvoiceCustomerInput" type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. + const: "N" + description: "Document type for this input variant." complements: type: array items: - $ref: "#/components/schemas/NominaOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complements to include in the invoice. related_documents: type: array @@ -17470,16 +18419,12 @@ components: allOf: - type: object properties: + customer: + $ref: "#/components/schemas/InvoiceCustomerInput" type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Type of document. It can have the values `"I"`: Income, `"P"`: Payment, `"E"`: Egress, `"N"`: Payroll, `"T"`: Transfer. + const: "T" + description: "Document type for this input variant." items: type: array maxItems: 5000 @@ -17493,7 +18438,7 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complements to include in the invoice. You can include any complement in the invoice if you build the XML node of the complement yourself and use the `custom` type. @@ -17522,22 +18467,30 @@ components: Receipt: title: Receipt object allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/ReceiptProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/ReceiptProperties' + - type: object + properties: + organization: + description: "ID of the organization this resource belongs to." + type: string ReceiptProperties: allOf: - type: object + required: + - date + - expires_at properties: date: type: string format: date-time - example: 2021-09-10T15:21:23.456Z + example: "2021-09-10T15:21:23.456Z" description: | Date of issuance of the receipt in ISO8601 format (UTC String). expires_at: type: string format: date-time - example: 2021-09-17T15:21:23.456Z + example: "2021-09-17T15:21:23.456Z" description: | Expiration date in ISO8601 format (UTC String). @@ -17629,7 +18582,7 @@ components: to issue a receipt with more than 5,000 concepts, you can divide the transaction into several receipts. items: $ref: "#/components/schemas/LineItemInput" - + - $ref: "#/components/schemas/ReceiptEditableProperties" - type: object properties: @@ -17645,7 +18598,7 @@ components: date: type: string format: date-time - example: 2021-09-10T15:21:23.456Z + example: "2021-09-10T15:21:23.456Z" description: | Date of issuance of the receipt in ISO8601 format (UTC String). payment_form: @@ -17692,6 +18645,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -17725,25 +18680,37 @@ components: description: Payment conditions. Free text field usually used to specify payment terms, such as the due date. - $ref: "#/components/schemas/InvoiceableCommonInput" GlobalInvoiceInput: + description: Dates are optional when selecting a period. Explicit receipts require both from and to. Periodicity defaults to the organization configuration. + anyOf: + - title: Select by period + allOf: + - $ref: '#/components/schemas/GlobalInvoiceInputProperties' + - type: object + properties: + receipts: false + - title: Select explicit receipts + required: + - receipts + - from + - to + allOf: + - $ref: '#/components/schemas/GlobalInvoiceInputProperties' + GlobalInvoiceInputProperties: type: object - required: - - periodicity properties: from: - type: string - format: date - default: Start of the last period - example: 2022-01-01T00:00:00.000 + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-01' description: | Initial date of the receipts that will be included in the global invoice. By default, this value is the start of the last period (day, week, fortnight, or month), according to the value of "Periodicity" (`periodicity`) in the receipts configuration of your organization. This value is required when the `receipts` field is sent. to: - type: string - format: date - default: End of the last period - example: 2022-01-31T23:59:59.999 + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-31' description: | End date of the receipts that will be included in the global invoice. By default, this value is the end of the last period (day, week, @@ -17751,28 +18718,28 @@ components: in the receipts configuration of your organization. This value is required when the `receipts` field is sent. periodicity: type: string - # default: Propiedad `periodicity` de la configuración de recibos de la organización. - default: "`periodicity` property from the organization's receipt configuration." enum: - day - week - fortnight - month - two_months - description: | + description: |- Periodicity that corresponds to the range of dates used. If you omit the `from` and `to` fields, the default dates will depend on the value of `periodicity`. + + If omitted, the organization’s receipt periodicity setting is used. months: type: string - default: Month contained in the range of dates used. - description: | + description: |- Key representing the month or bimester of the invoice. Consult the possible values in the [Months and Bimesters catalog](#meses-y-bimestres). - example: "01" + + If omitted, the month or two-month period is determined from the start date and periodicity. + example: '01' folio_number: type: integer - default: autoincremental description: | Number of the folio assigned by the company for internal control. If omitted, the incremental value of the organization will be assigned. @@ -17780,19 +18747,17 @@ components: type: string maxLength: 25 description: Series. Alphanumeric characters designated by the company for internal control and without fiscal validity. - example: "F" + example: F date: - type: string - format: date - default: Value of the `to` field - example: 2022-01-01T00:00:00.000 - description: | - Date of issuance of the invoice. By default, it takes the value of the `to` field. + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-01' + description: Invoice issuance date. If omitted, the end date (`to`) is used, capped at the current date and time. payment_form: type: string minLength: 2 maxLength: 2 - example: "02" + example: '02' description: | Payment form code according to the [Payment Form catalog](#forma-de-pago). @@ -17853,8 +18818,7 @@ components: default: false description: If `true`, only validates data and returns a summary without creating the invoice. payment_form: - type: string - nullable: true + type: ["string","null"] minLength: 2 maxLength: 2 example: "03" @@ -17875,13 +18839,13 @@ components: description: Receipt key. example: ticket_1001 customer: - nullable: true oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" + - $ref: '#/components/schemas/CustomerCreateInput' - type: string title: customer_id description: ID of a customer previously registered in Facturapi. example: 58e93bd8e86eb318b0197456 + - type: 'null' description: | Optional customer used for preview rendering. If you omit it, all receipts must already have the same assigned customer. @@ -17891,13 +18855,83 @@ components: description: CFDI Use code according to SAT catalog. ToInvoiceSummary: type: object - description: Summary object returned when `dry_run=true`. + description: Receipt amounts and taxes returned when `dry_run=true`. + required: [subtotal, discount, taxes, total, receipts, payment_form, item_count] + properties: + subtotal: + type: number + discount: + type: number + total: + type: number + receipts: + type: array + items: + type: string + payment_form: + type: string + item_count: + type: integer + taxes: + type: object + required: [totalAdded, totalWithholding, allAdded, allWithholding, localTotalAdded, localTotalWithholding, localAllAdded, localAllWithholding] + properties: + totalAdded: + type: number + totalWithholding: + type: number + localTotalAdded: + type: number + localTotalWithholding: + type: number + allAdded: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + allWithholding: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + localAllAdded: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + localAllWithholding: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + ReceiptInvoiceSummaryTax: + type: object + required: [factor, withholding, base, amount] + additionalProperties: true + properties: + type: + type: string + rate: + type: number + factor: + type: string + enum: [Tasa, Cuota, Exento] + withholding: + type: boolean + base: + type: number + amount: + type: number + name: + type: string + Retention: title: Retention object allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/RetentionReadOnlyProperties" - - $ref: "#/components/schemas/RetentionProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/RetentionReadOnlyProperties' + - $ref: '#/components/schemas/RetentionProperties' + - type: object + properties: + organization: + description: "ID of the organization this resource belongs to." + type: string RetentionReadOnlyProperties: type: object properties: @@ -17929,9 +18963,13 @@ components: Fiscal folio of the retention, assigned by the SAT. example: 39c85a3f-275b-4341-b259-e8971d9f8a94 stamp: - $ref: "#/components/schemas/Stamp" + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' customer: - $ref: "#/components/schemas/CustomerInfo" + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' is_ready_to_stamp: type: boolean description: | @@ -17940,16 +18978,20 @@ components: example: false RetentionProperties: type: object + required: + - fecha_exp properties: cve_retenc: type: string - example: 01 + example: "01" description: | Key of the retention or payment information according to the SAT catalog. fecha_exp: - type: string + type: + - string + - 'null' format: date-time - example: "2021-09-15T06:03:23.000Z" + example: '2021-09-15T06:03:23.000Z' description: Date of issuance of the document in ISO8601 format (UTC String). desc_retenc: type: string @@ -18023,10 +19065,10 @@ components: tipo_pago_ret: type: string enum: - - 01 - - 02 - - 03 - - 04 + - "01" + - "02" + - "03" + - "04" description: | Key of the type of payment according to the SAT catalog. @@ -18048,7 +19090,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CustomComplementData" + $ref: '#/components/schemas/CustomComplementData' description: | Array of complements to include in the retention. Each element contains a `string` with the XML code of the complement. pdf_custom_section: @@ -18064,11 +19106,13 @@ components: type: array description: Namespaces to insert in the root node of the invoice. Required for `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' RetentionSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -18130,16 +19174,15 @@ components: example: draft customer: description: Customer receiving the invoice. - nullable: true oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" + - $ref: '#/components/schemas/CustomerCreateInput' - type: string title: customer_id description: ID of the 'customer' object previously registered in Facturapi. example: 58e93bd8e86eb318b0197456 + - type: 'null' cve_retenc: - type: string - nullable: true + type: ["string","null"] example: 26 description: Key of the retention or payment information according to the [SAT catalog](#clave-de-retencion). fecha_exp: @@ -18156,8 +19199,7 @@ components: example: R123 description: Alphanumeric identifier for internal control of the company and without fiscal relevance. periodo: - type: object - nullable: true + type: ["object","null"] description: Information about the retention period. required: - mes_ini @@ -18181,8 +19223,7 @@ components: example: 2021 description: Fiscal year in which the retention was made. totales: - type: object - nullable: true + type: ["object","null"] description: Information about the total of retentions made in the corresponding period. required: - monto_tot_operacion @@ -18238,10 +19279,10 @@ components: tipo_pago_ret: type: string enum: - - 01 - - 02 - - 03 - - 04 + - "01" + - "02" + - "03" + - "04" description: | Key of the type of payment according to the SAT catalog. @@ -18295,6 +19336,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -18303,25 +19346,30 @@ components: Organization: title: Organization object type: object + required: + - id + - created_at + - certificate + - fiel properties: id: type: string description: ID of the organization, assigned by Facturapi. - example: "5a2a307be93a2f00129ea035" + example: 5a2a307be93a2f00129ea035 created_at: type: string format: date-time description: Date and time of creation of the organization. - example: "2017-05-05T20:55:33.468Z" + example: '2017-05-05T20:55:33.468Z' logo_url: type: string format: uri description: URL of the organization's logo. - example: "https://storage.googleapis.com/cdn.facturapi.io/organization/6c100efa5c6f5d7db0379ca643476a4183526007/logo.jpg" + example: https://storage.googleapis.com/cdn.facturapi.io/organization/6c100efa5c6f5d7db0379ca643476a4183526007/logo.jpg timezone: type: string description: Time zone of the organization, in IANA format. - example: "America/Mexico_City" + example: America/Mexico_City is_production_ready: type: boolean description: Indicates if the organization has the necessary information to issue invoices in the Live environment. @@ -18356,7 +19404,7 @@ components: Fiscal or Legal Name of the organization, *without* the corporate regime (e.g.: S.A. de C.V.). tax_system: type: string - example: "601" + example: '601' maxLength: 3 minLength: 3 description: Fiscal Regime Code, from the [SAT catalog](#régimen-fiscal). @@ -18370,7 +19418,7 @@ components: allOf: - type: object description: Fiscal address of the organization. - - $ref: "#/components/schemas/OrganizationAddress" + - $ref: '#/components/schemas/OrganizationAddress' customization: type: object description: | @@ -18490,16 +19538,16 @@ components: updated_at: type: string format: date-time - example: "2023-05-05T20:55:33.468Z" - description: Date of the last update of the certificate. + example: '2023-05-05T20:55:33.468Z' + description: Date of the last update of the certificate. Omitted when no certificate is uploaded. expires_at: type: string format: date-time - example: "2025-05-05T20:55:33.468Z" - description: Expiration date of the certificate. + example: '2025-05-05T20:55:33.468Z' + description: Expiration date of the certificate. Omitted when no certificate is uploaded. serial_number: type: string - example: "20001000000300000000" + example: '20001000000300000000' description: Serial number of the certificate. fiel: type: object @@ -18512,16 +19560,16 @@ components: updated_at: type: string format: date-time - example: "2023-05-05T20:55:33.468Z" - description: Date of the last update of the FIEL certificate. + example: '2023-05-05T20:55:33.468Z' + description: Date of the last update of the FIEL certificate. Omitted when no certificate is uploaded. expires_at: type: string format: date-time - example: "2025-05-05T20:55:33.468Z" - description: Expiration date of the FIEL certificate. + example: '2025-05-05T20:55:33.468Z' + description: Expiration date of the FIEL certificate. Omitted when no certificate is uploaded. serial_number: type: string - example: "20001000000300000000" + example: '20001000000300000000' description: Serial number of the FIEL certificate. receipts: type: object @@ -18593,6 +19641,45 @@ components: support_email_verified: type: boolean description: Indicates if the support email has been verified. If false, the email used in the self-invoice portal will be the main account's email. + plan: + type: + - string + - 'null' + deprecated: true + description: Legacy organization plan. + add_ons: + type: array + description: Additional features contracted for the organization. + items: + type: string + pending_plan_update: + type: + - object + - 'null' + description: Scheduled plan change, when present. + properties: + plan: + type: string + scheduled_for: + type: string + format: date-time + pending_add_ons_update: + type: + - object + - 'null' + description: Scheduled additional-feature change, when present. + properties: + add_ons: + type: array + items: + type: string + scheduled_for: + type: string + format: date-time + domain: + type: string + custom_domain: + type: string OrganizationDeleteCerts: type: object @@ -18922,11 +20009,11 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Invoice type. Possible values: `I` (Income), `E` (Expense), `P` (Payment), `N` (Payroll), `T` (Transfer). @@ -18961,6 +20048,9 @@ components: example: true OrganizationInvite: type: object + required: + - created_at + - expires_at properties: id: type: string @@ -18977,12 +20067,10 @@ components: type: string description: Name of the organization that sent the invite. role: - type: string - nullable: true + type: ["string","null"] description: ID of the role assigned in the invite, if any. role_name: - type: string - nullable: true + type: ["string","null"] description: Name of the role assigned in the invite, if any. roles: type: array @@ -18990,9 +20078,8 @@ components: items: type: string expires_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Date and time when the invite expires. OrganizationInviteList: type: array @@ -19001,6 +20088,9 @@ components: $ref: "#/components/schemas/OrganizationInvite" OrganizationPermissionRole: type: object + required: + - created_at + - updated_at properties: id: type: string @@ -19009,12 +20099,10 @@ components: type: string description: Role name. template_code: - type: string - nullable: true + type: ["string","null"] description: Base template code for the role, if it comes from a system template. organization: - type: string - nullable: true + type: ["string","null"] description: ID of the organization the role belongs to. used_by: type: integer @@ -19035,14 +20123,12 @@ components: items: type: string created_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Date and time when the role was created. updated_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Date and time when the role was last updated. OrganizationPermissionRoleList: type: array @@ -19081,6 +20167,9 @@ components: type: string OrganizationUserAccess: type: object + required: + - created_at + - updated_at properties: id: type: string @@ -19093,16 +20182,13 @@ components: format: email description: User email address. role: - type: string - nullable: true + type: ["string","null"] description: ID of the role assigned to the user, if any. For the owner, this value is `null` because the access is implicit. role_name: - type: string - nullable: true + type: ["string","null"] description: Name of the assigned role or of the user's implicit access. For the owner, this value is `owner`. organization: - type: string - nullable: true + type: ["string","null"] description: ID of the organization this access belongs to. operations: type: array @@ -19152,14 +20238,14 @@ components: type: string description: Role name. template_code: - type: string - nullable: true + type: ["string","null"] enum: - org-admin - org-readonly - org-billing - org-developer - org-team-manager + - null description: Base template code used to initialize the role, if any. add: type: array @@ -19178,14 +20264,14 @@ components: type: string description: New role name. template_code: - type: string - nullable: true + type: ["string","null"] enum: - org-admin - org-readonly - org-billing - org-developer - org-team-manager + - null description: New base template code for the role, if any. add: type: array diff --git a/website/openapi_v2.yaml b/website/openapi_v2.yaml index 1491a0772..1351317e5 100644 --- a/website/openapi_v2.yaml +++ b/website/openapi_v2.yaml @@ -33,7 +33,7 @@ info: Durante el desarrollo, puedes usar la API de Facturapi en ambiente Test y las facturas que emitas no se enviarán al SAT ni tendrán validez fiscal. - + La llave secreta que utilices para autenticarte determinará tanto el ambiente en el que se creará la factura (Test o Live), así como la organización a utilizar como emisor @@ -961,6 +961,7 @@ x-tagGroups: paths: /catalogs/cartaporte/3.1/air-transport-codes: get: + operationId: "searchCartaPorteAirTransportCodes" tags: - carta_porte_keys summary: Buscar códigos de transporte aéreo @@ -1018,10 +1019,9 @@ paths: ["limit"] = 10 }); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - + - $ref: '#/components/parameters/SearchPagination' + - $ref: '#/components/parameters/SearchAfter' + - $ref: '#/components/parameters/SearchBefore' - in: query name: q schema: @@ -1049,34 +1049,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/comercioexterior/2.0/tariff-fractions: get: + operationId: "searchComercioExteriorTariffFractions" tags: - comercio_exterior_keys summary: Buscar fracciones arancelarias @@ -1133,10 +1118,9 @@ paths: ["limit"] = 10 }); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - + - $ref: '#/components/parameters/SearchPagination' + - $ref: '#/components/parameters/SearchAfter' + - $ref: '#/components/parameters/SearchBefore' - in: query name: q schema: @@ -1164,34 +1148,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/transport-configs: get: + operationId: "searchCartaPorteTransportConfigs" tags: - carta_porte_keys summary: Buscar configuraciones de autotransporte @@ -1279,34 +1248,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/rights-of-passage: get: + operationId: "searchCartaPorteRightsOfPassage" tags: - carta_porte_keys summary: Buscar derechos de paso @@ -1394,34 +1348,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/customs-documents: get: + operationId: "searchCartaPorteCustomsDocuments" tags: - carta_porte_keys summary: Buscar documentos aduaneros @@ -1509,34 +1448,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/packaging-types: get: + operationId: "searchCartaPortePackagingTypes" tags: - carta_porte_keys summary: Buscar tipos de empaque @@ -1624,34 +1548,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/trailer-types: get: + operationId: "searchCartaPorteTrailerTypes" tags: - carta_porte_keys summary: Buscar tipos de remolque @@ -1739,34 +1648,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/hazardous-materials: get: + operationId: "searchCartaPorteHazardousMaterials" tags: - carta_porte_keys summary: Buscar materiales peligrosos @@ -1854,34 +1748,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/naval-authorizations: get: + operationId: "searchCartaPorteNavalAuthorizations" tags: - carta_porte_keys summary: Buscar autorizaciones navales @@ -1968,7 +1847,7 @@ paths: application/json: schema: allOf: - - $ref: "#/components/schemas/SearchResult" + - $ref: '#/components/schemas/SearchResult' - type: object properties: data: @@ -1979,34 +1858,19 @@ paths: key: type: string '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/port-stations: get: + operationId: "searchCartaPortePortStations" tags: - carta_porte_keys summary: Buscar estaciones/puertos @@ -2094,34 +1958,19 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /catalogs/cartaporte/3.1/marine-containers: get: + operationId: "searchCartaPorteMarineContainers" tags: - carta_porte_keys summary: Buscar contenedores marítimos @@ -2209,31 +2058,15 @@ paths: schema: $ref: '#/components/schemas/SearchKeyDescriptionResult' '400': - description: Error en parámetros de la petición - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/BadRequest' '401': - description: Error de autenticación - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/Unauthenticated' '404': - description: No se encontró el recurso especificado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/RateLimited' '500': - description: Error inesperado - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' + $ref: '#/components/responses/UnexpectedError' /customers: post: operationId: createCustomer @@ -2251,7 +2084,7 @@ paths: 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_. x-codeSamples: @@ -2340,9 +2173,10 @@ paths: description: | 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 7 días y sólo se podrá usar una vez. + 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`. security: - "SecretLiveKey": [] - "SecretTestKey": [] @@ -2628,7 +2462,7 @@ paths: description: | 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 7 días y sólo se podrá usar una vez. Pasar el valor `true` al editar + 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. requestBody: $ref: "#/components/requestBodies/CustomerEdit" @@ -2724,7 +2558,7 @@ paths: description: | 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 7 días y sólo se podrá usar una vez. + Este enlace estará disponible en el campo `edit_link`, será válido por 3 días y sólo se podrá usar una vez. x-codeSamples: - lang: Bash label: cURL @@ -2929,7 +2763,7 @@ paths: Puedes usar el ID del producto para crear facturas sin tener que enviar todos los datos del producto cada vez. - Te en cuenta que los productos que crees en ambiente _Test_ **no se + Ten en cuenta que los productos que crees en ambiente _Test_ **no se comparten** con el ambiente _Live_. x-codeSamples: - lang: Bash @@ -3200,10 +3034,7 @@ paths: const product = await facturapi.products.update( '590e22c26d04f840aa8438b2', { - email: 'jdoe@example.com', - address: { - street: 'Santa Monica Ave.' - } + price: 456.70 } ); - lang: csharp @@ -3497,12 +3328,9 @@ paths: content: application/json: schema: - type: object - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/Invoice" - draft: "#/components/schemas/InvoiceDraft" + anyOf: + - $ref: "#/components/schemas/Invoice" + - $ref: "#/components/schemas/InvoiceDraft" "202": description: Solicitud aceptada; Facturapi intentará recuperar el CFDI hasta cinco veces, una cada 10 minutos content: @@ -3528,7 +3356,7 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - + get: operationId: listInvoices tags: @@ -3566,16 +3394,16 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // Todas las facturas de la organización - const invoiceSearch = await facturapi.invoices.list(); + const invoiceSearch1 = await facturapi.invoices.list(); // Todas las facturas emitidas para cierto cliente - const invoiceSearch = await facturapi.invoices.list({ + const invoiceSearch2 = await facturapi.invoices.list({ customer: '590ce6c56d04f840aa8438af' }); // Página 3 de los resultados de búsqueda de texto libre // de facturas emitidas por cierto cliente entre 2017 y 2019 - const invoiceSearch = await facturapi.invoices.list({ + const invoiceSearch3 = await facturapi.invoices.list({ q: 'Aspiradora Robot', customer: '590ce6c56d04f840aa8438af', date: { @@ -3690,11 +3518,11 @@ paths: schema: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: Tipo de factura. Búsqueda por tipo de factura con las claves exactas. - in: query name: payment_method @@ -3791,58 +3619,30 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests: - post: - operationId: createInvoiceZipRequest + /invoices/{invoice_id}: + get: + operationId: getInvoice tags: - invoice - summary: Crear o recuperar solicitud de ZIP mensual - description: | - 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. + summary: Obtener factura por ID + description: Regresa el objeto 'Invoice' relacionado al `id` especificado. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests \ - -H "Authorization: Bearer sk_live_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "year": 2025, - "month": 3, - "issuer_type": "issuing", - "invoice_types": ["I", "E"] - }' + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequest = await facturapi.invoices.createZipRequest({ - year: 2025, - month: 3, - issuer_type: 'issuing', - invoice_types: ['I', 'E'] - }); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.retrieve('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequest = await facturapi.Invoice.CreateZipRequestAsync( - new Dictionary - { - ["year"] = 2025, - ["month"] = 3, - ["issuer_type"] = "issuing", - ["invoice_types"] = new[] { "I", "E" } - } - ); + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.RetrieveAsync("58e93bd8e86eb318b019743d"); - lang: Java label: Java source: | @@ -3850,496 +3650,455 @@ paths: import java.util.List; import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequest = facturapi.invoices().createZipRequest( - Map.of( - "year", 2025, - "month", 3, - "issuer_type", "issuing", - "invoice_types", List.of("I", "E") - ) - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().retrieve( + "inv_123" + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequest = $facturapi->Invoices->createZipRequest([ - "year" => 2025, - "month" => 3, - "issuer_type" => "issuing", - "invoice_types" => ["I", "E"] - ]); - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/InvoiceZipRequestCreateInput" + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->retrieve( "58e93bd8e86eb318b019743d" ); + parameters: + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID del objeto a obtener security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Solicitud de ZIP creada o recuperada correctamente. + description: Objeto `Invoice` content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequest" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNoInvoices" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - get: - operationId: listInvoiceZipRequests + put: + operationId: updateDraftInvoice tags: - invoice - summary: Listar solicitudes de ZIP mensual + summary: Editar borrador de factura description: | - 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. + 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`. x-codeSamples: - lang: Bash label: cURL source: | - curl "https://www.facturapi.io/v2/invoices/zip-requests?year=2025&month=3&status=finished&limit=20&page=1" \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + -X PUT \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "payment_form": "06" + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequests = await facturapi.invoices.listZipRequests({ - year: 2025, - month: 3, - status: 'finished', - limit: 20, - page: 1 - }); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.updateDraft( + '58e93bd8e86eb318b019743d', + { + payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO + } + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequests = await facturapi.Invoice.ListZipRequestsAsync( + var facturapi = new Facturapi("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.UpdateDraftAsync( + "58e93bd8e86eb318b019743d", new Dictionary { - ["year"] = 2025, - ["month"] = 3, - ["status"] = "finished", - ["limit"] = 20, - ["page"] = 1 + ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO } ); - lang: Java label: Java source: | import io.facturapi.Facturapi; + import java.util.List; import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequests = facturapi.invoices().listZipRequests( - Map.of( - "year", 2025, - "month", 3, - "status", "finished", - "limit", 20, - "page", 1 - ) - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().updateDraft("inv_123", Map.of( + "items", List.of( + Map.of( + "quantity", 1, + "product", "prod_123" + ) + ) + )); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequests = $facturapi->Invoices->listZipRequests([ - "year" => 2025, - "month" => 3, - "status" => "finished", - "limit" => 20, - "page" => 1 + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->updateDraft("58e93bd8e86eb318b019743d", [ + "payment_form" => \Facturapi\PaymentForm::EFECTIVO ]); parameters: - - in: query - name: year - schema: - type: integer - minimum: 2000 - maximum: 9999 - description: Año a filtrar. Debe enviarse junto con `month`. - - in: query - name: month - schema: - type: integer - minimum: 1 - maximum: 12 - description: Mes a filtrar. Debe enviarse junto con `year`. - - in: query - name: status - schema: - $ref: "#/components/schemas/InvoiceZipRequestStatus" - description: Status de la solicitud. - - in: query - name: issuer_type - schema: - $ref: "#/components/schemas/IssuingType" - description: Filtra facturas emitidas o recibidas. - - in: query - name: invoice_types - schema: - type: array - uniqueItems: true - items: - $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" - description: Filtra por un tipo de factura o por un arreglo normalizado exacto. - - in: query - name: page + - in: path + name: invoice_id schema: - type: integer - minimum: 1 - default: 1 - description: Página de resultados, empezando en 1. - - $ref: "#/components/parameters/SearchLimit" + type: string + required: true + description: ID del objeto a editar + requestBody: + $ref: "#/components/requestBodies/InvoiceEdit" security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Resultado paginado de solicitudes de ZIP. + description: Objeto `Invoice` editado correctamente content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequestSearchResult" + $ref: "#/components/schemas/InvoiceDraft" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}: - get: - operationId: retrieveInvoiceZipRequest + delete: + operationId: cancelInvoice tags: - invoice - summary: Recuperar solicitud de ZIP mensual + summary: Cancelar factura description: | - 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. + Realiza una solicitud de cancelación de factura ante el SAT, soportando el esquema de cancelación 2022. - Requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000 \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d?motive=02 \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X DELETE - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipRequest = await facturapi.invoices.retrieveZipRequest( - '66b0f0000000000000000000' + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.cancel( + '58e93bd8e86eb318b019743d', + { motive: '02' } ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipRequest = await facturapi.Invoice.RetrieveZipRequestAsync( - "66b0f0000000000000000000" + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.CancelAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["motive"] = "02" + } ); - lang: Java label: Java source: | import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - var zipRequest = facturapi.invoices().retrieveZipRequest( - "66b0f0000000000000000000" - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.invoices().cancel( + "inv_123", + Map.of( + "motive", "02" + ) + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zipRequest = $facturapi->Invoices->retrieveZipRequest( - "66b0f0000000000000000000" + $facturapi = new Facturapi("sk_test_API_KEY"); + $canceled_invoice = $facturapi->Invoices->cancel( + "58e93bd8e86eb318b019743d", + [ + "motive" => "02" + ] ); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID de la factura a cancelar + - in: query + name: motive + required: false + schema: + type: string + enum: + - '01' + - '02' + - '03' + - '04' + description: | + 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. + - in: query + name: substitution + required: false + schema: + type: string + description: | + 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. security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Solicitud de ZIP recuperada correctamente. + description: Solicitud de cancelación exitosa content: application/json: schema: - $ref: "#/components/schemas/InvoiceZipRequest" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}/zip: - get: - operationId: downloadInvoiceZipRequest + /invoices/{invoice_id}/copy: + post: + operationId: copyToDraftInvoice tags: - invoice - summary: Descargar ZIP mensual + summary: Copiar a borrador description: | - 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. + Crea una copia en borrador de la factura especificada. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/zip \ - -H "Authorization: Bearer sk_live_API_KEY" \ - --output 2025-03.zip + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/copy \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST - lang: JavaScript label: Node.js source: | - import fs from 'fs'; - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_live_API_KEY'); - const zipStream = await facturapi.invoices.downloadZipRequest( - '66b0f0000000000000000000' - ); - zipStream.pipe(fs.createWriteStream('./2025-03.zip')); + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const invoice = await facturapi.invoices.copyToDraft('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_live_API_KEY"); - var zipStream = await facturapi.Invoice.DownloadZipRequestAsync( - "66b0f0000000000000000000" - ); - await using var file = File.Create("2025-03.zip"); - await zipStream.CopyToAsync(file); + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Invoice.CopyToDraftAsync("58e93bd8e86eb318b019743d"); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.io.InputStream; - import java.nio.file.Files; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; + import java.util.List; + import java.util.Map; - Facturapi facturapi = new Facturapi("sk_live_API_KEY"); - try (InputStream zipStream = facturapi.invoices().downloadZipRequest( - "66b0f0000000000000000000" - )) { - Files.copy(zipStream, Path.of("./2025-03.zip"), StandardCopyOption.REPLACE_EXISTING); - } + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var draft = facturapi.invoices().copyToDraft( + "inv_123" + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_live_API_KEY"); - $zip = $facturapi->Invoices->downloadZipRequest( - "66b0f0000000000000000000" - ); - file_put_contents("2025-03.zip", $zip); + $facturapi = new Facturapi("sk_test_API_KEY"); + $invoice = $facturapi->Invoices->copyToDraft("58e93bd8e86eb318b019743d"); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID de la factura a copiar security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: Archivo ZIP generado. - headers: - Content-Disposition: - description: Nombre sugerido con formato `attachment; filename="YYYY-MM.zip"`. - schema: - type: string + description: Nuevo objeto `Invoice` con status `draft`. content: - application/zip: + application/json: schema: - type: string - format: binary + $ref: "#/components/schemas/InvoiceDraft" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" - "409": - $ref: "#/components/responses/InvoiceZipRequestNotReady" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/zip-requests/{id}/download-url: - get: - operationId: getInvoiceZipRequestDownloadUrl + /invoices/{invoice_id}/stamp: + post: + operationId: stampDraftInvoice tags: - invoice - summary: Obtener URL de descarga del ZIP mensual + summary: Timbrar borrador de factura description: | - Devuelve una URL temporal para descargar el ZIP de una solicitud terminada sin que el archivo viaje a través de tu servidor. + Timbra una factura con status `draft` y la envía al SAT para su validación. - 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. + 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). x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/download-url \ - -H "Authorization: Bearer sk_live_API_KEY" + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/stamp \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + const stampedInvoice = await facturapi.invoices.stampDraft('58e93bd8e86eb318b019743d'); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var stampedInvoice = await facturapi.Invoice.StampDraftAsync("58e93bd8e86eb318b019743d"); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - const facturapi = new Facturapi('sk_live_API_KEY'); - const download = await facturapi.invoices.downloadZipRequestUrl( - '66b0f0000000000000000000' - ); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - console.log(download.url, download.expires_at); + var invoice = facturapi.invoices().stampDraft( + "inv_123", + Map.of( + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + $stamped_invoice = $facturapi->Invoices->stampDraft("58e93bd8e86eb318b019743d"); parameters: - - $ref: "#/components/parameters/InvoiceZipRequestId" + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID del objeto a timbrar + - in: query + name: async + schema: + type: boolean + required: false + description: | + Ú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. security: - "SecretLiveKey": [] + - "SecretTestKey": [] responses: "200": - description: URL temporal de descarga para el archivo ZIP generado. + description: Objeto `Invoice` timbrado correctamente content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "402": - $ref: "#/components/responses/InvoiceZipRequestAccessRequired" - "404": - $ref: "#/components/responses/InvoiceZipRequestNotFound" "409": - $ref: "#/components/responses/InvoiceZipRequestNotReady" + $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/preview/pdf: - post: - operationId: previewInvoicePdf + + /invoices/{invoice_id}/status: + put: + operationId: updateInvoiceStatus tags: - invoice - summary: Vista previa de factura en PDF - description: Genera una vista previa en PDF de una factura sin timbrar ni guardar en la organización. + summary: | + Actualizar status de factura + description: | + Consulta el status de una factura timbrada en el SAT y actualiza el objeto invoice + con La información más reciente. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/preview/pdf \ + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/status \ -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "customer": { - "legal_name": "Dunder Mifflin", - "email": "email@example.com", - "tax_id": "ABC101010111", - "tax_system": "601", - "address": { - "zip": "85900" - } - }, - "items": [{ - "quantity": 2, - "product": { - "description": "Ukelele", - "product_key": "60131324", - "price": 345.60 - } - }], - "payment_form": "06", - "folio_number": 914, - "series": "F" - }' + -X PUT - lang: JavaScript label: Node.js source: | - const Facturapi = require('facturapi'); + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const pdfStream = await facturapi.invoices.previewPdf({ - customer: { - legal_name: 'Dunder Mifflin', - email: 'email@example.com', - tax_id: 'ABC101010111', - tax_system: '601', - address: { - zip: '85900' - } - }, - items: [{ - quantity: 2, - product: { - description: 'Ukelele', - product_key: '60131324', - price: 345.60 - } - }], - payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO, - folio_number: 914, - series: 'F' - }); - // Save PDF stream to a file - const fs = require('fs'); - const file = fs.createWriteStream('invoice_preview.pdf'); - pdfStream.pipe(file); + const invoice = await facturapi.invoices.updateStatus('58e93bd8e86eb318b019743d'); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var pdfStream = await facturapi.Invoice.PreviewPdfAsync(new Dictionary - { - ["customer"] = new Dictionary - { - ["legal_name"] = "Dunder Mifflin", - ["email"] = "email@example.com", - ["tax_id"] = "ABC101010111", - ["tax_system"] = "601", - ["address"] = new Dictionary - { - ["zip"] = "85900" - } - }, - ["items"] = new Dictionary[] - { - new Dictionary - { - ["product"] = new Dictionary - { - ["description"] = "Ukelele", - ["product_key"] = "60131324", - ["price"] = 345.60 - } - } - }, - ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO, - ["folio_number"] = 914, - ["series"] = "F" - }); - // Save PDF stream to a file - var file = new System.IO.FileStream("invoice_preview.pdf", System.IO.FileMode.Create, System.IO.FileAccess.Write); - pdfStream.CopyTo(file); - file.Close(); - - lang: Java + var facturapi = new Facturapi + var invoice = await facturapi.Invoice.UpdateStatusAsync("58e93bd8e86eb318b019743d"); + - lang: Java label: Java source: | import io.facturapi.Facturapi; @@ -4348,94 +4107,30 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var pdf = facturapi.invoices().previewPdf( - Map.of( - "customer", "cus_123", - "items", List.of( - Map.of( - "quantity", 1, - "product", "prod_123" - ) - ) - )); + var invoice = facturapi.invoices().updateStatus( + "inv_123" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $pdfBytes = $facturapi->Invoices->previewPdf([ - "customer" => [ - "legal_name" => "Dunder Mifflin", - "email" => "email@example.com", - "tax_id" => "ABC101010111", - "tax_system" => "601", - "address" => [ - "zip" => "85900" - ] - ], - "items" => [ - [ - "quantity" => 2, - "product" => [ - "description" => "Ukelele", - "product_key" => "60131324", - "price" => 345.60, - "sku" => "ABC4567" - ] - ] - ], - "payment_form" => \Facturapi\PaymentForm::EFECTIVO, - "folio_number" => 914, - "series" => "F" - ]); - requestBody: - $ref: "#/components/requestBodies/InvoiceCreate" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: El archivo PDF de la factura - content: - application/pdf: - schema: - type: string - format: binary - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /invoices/preview/pdf/download-url: - post: - operationId: previewInvoicePdfUrl - tags: - - invoice - summary: Obtener URL del preview PDF de factura - description: Devuelve una URL temporal para el preview PDF de una factura sin timbrar. - x-codeSamples: - - lang: JavaScript - label: Node.js - source: | - const download = await facturapi.invoices.previewPdfUrl({ - customer: 'cus_123', - items: [{ product: 'prod_123' }], - payment_form: '06' - }); - console.log(download.url, download.expires_at); - requestBody: - $ref: "#/components/requestBodies/InvoiceCreate" + $invoice = $facturapi->Invoices->updateStatus("58e93bd8e86eb318b019743d"); + parameters: + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID del objeto invoice a actualizar security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: URL temporal de descarga para el preview PDF. + description: Objeto `Invoice` actualizado content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/Invoice" "400": $ref: "#/components/responses/BadRequest" "401": @@ -4444,118 +4139,283 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}: + + /invoices/{invoice_id}/payment-summary: get: - operationId: getInvoice + operationId: getInvoicePaymentSummary tags: - invoice - summary: Obtener factura por ID - description: Regresa el objeto 'Invoice' relacionado al `id` especificado. + summary: Resumen de pago + description: | + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ + curl "https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/payment-summary?amount=100" \ -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.retrieve('58e93bd8e86eb318b019743d'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.RetrieveAsync("58e93bd8e86eb318b019743d"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + const summary = await facturapi.invoices.paymentSummary( + '58e93bd8e86eb318b019743d', + { amount: 100 } + ); - var invoice = facturapi.invoices().retrieve( - "inv_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->retrieve( "58e93bd8e86eb318b019743d" ); + // El resumen va completo como related_document del complemento + const invoice = await facturapi.invoices.create({ + type: 'P', + customer: 'customer_id', + complements: [ + { + type: 'pago', + data: [ + { + payment_form: '28', + related_documents: [summary] + } + ] + } + ] + }); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID del objeto a obtener + description: ID de la factura de ingreso (método de pago PPD) que se desea pagar + - in: query + name: amount + schema: + type: number + required: true + description: Monto que se paga de esta factura, expresado en la divisa de la factura. No puede exceder el saldo pendiente. security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Objeto `Invoice` + description: Resumen del documento relacionado content: application/json: schema: - $ref: "#/components/schemas/Invoice" + type: object + required: + - uuid + - series + - installment + - last_balance + - total + - currency + - amount + - taxes + properties: + uuid: + type: string + description: UUID de la factura + folio_number: + type: number + description: Folio de la factura. Se omite si la factura no lo tiene registrado. + series: + type: ["string","null"] + description: Serie de la factura + installment: + type: number + description: Número de parcialidad que corresponde a este pago + last_balance: + type: number + description: Saldo pendiente de la factura antes de aplicar este pago + total: + type: number + description: Total de la factura + currency: + type: string + description: Divisa de la factura + amount: + type: number + description: Monto que se paga en esta parcialidad + taxes: + type: array + description: Impuestos de la factura prorrateados al monto pagado + items: + type: object + required: + - base + - rate + - type + - factor + - withholding + properties: + base: + type: number + description: Base del impuesto prorrateada al monto pagado + rate: + type: number + description: Tasa o cuota del impuesto + type: + type: string + enum: + - IVA + - ISR + - IEPS + description: Tipo de impuesto (IVA, ISR, etc.) + factor: + type: string + enum: + - Tasa + - Cuota + - Exento + description: Tipo de factor (Tasa, Exento, etc.) + withholding: + type: boolean + description: Indica si se trata de una retención + example: + uuid: 39c85a3f-275b-4341-b259-e8971d9f8a94 + folio_number: 914 + series: F + installment: 2 + last_balance: 245.6 + total: 345.6 + currency: MXN + amount: 100 + taxes: + - base: 86.21 + rate: 0.16 + type: IVA + factor: Tasa + withholding: false "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - put: - operationId: updateDraftInvoice + + /invoices/preview/pdf: + post: + operationId: previewInvoicePdf tags: - invoice - summary: Editar borrador de factura - description: | - 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`. + summary: Vista previa de factura en PDF + description: Genera una vista previa en PDF de una factura sin timbrar ni guardar en la organización. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d \ - -X PUT \ + curl https://www.facturapi.io/v2/invoices/preview/pdf \ -H "Authorization: Bearer sk_test_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "payment_form": "06" - }' - - lang: JavaScript + "customer": { + "legal_name": "Dunder Mifflin", + "email": "email@example.com", + "tax_id": "ABC101010111", + "tax_system": "601", + "address": { + "zip": "85900" + } + }, + "items": [{ + "quantity": 2, + "product": { + "description": "Ukelele", + "product_key": "60131324", + "price": 345.60 + } + }], + "payment_form": "06", + "folio_number": 914, + "series": "F" + }' + - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' + import Facturapi from 'facturapi'; const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.updateDraft( - '58e93bd8e86eb318b019743d', - { - payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO - } - ); + const pdfStream = await facturapi.invoices.previewPdf({ + customer: { + legal_name: 'Dunder Mifflin', + email: 'email@example.com', + tax_id: 'ABC101010111', + tax_system: '601', + address: { + zip: '85900' + } + }, + items: [{ + quantity: 2, + product: { + description: 'Ukelele', + product_key: '60131324', + price: 345.60 + } + }], + payment_form: Facturapi.PaymentForm.DINERO_ELECTRONICO, + folio_number: 914, + series: 'F' + }); + // Save PDF stream to a file + import fs from 'node:fs'; + const file = fs.createWriteStream('invoice_preview.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(file); + } - lang: csharp label: C# source: | - var facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.UpdateDraftAsync( - "58e93bd8e86eb318b019743d", - new Dictionary + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var pdfStream = await facturapi.Invoice.PreviewPdfAsync(new Dictionary + { + ["customer"] = new Dictionary { - ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO - } - ); + ["legal_name"] = "Dunder Mifflin", + ["email"] = "email@example.com", + ["tax_id"] = "ABC101010111", + ["tax_system"] = "601", + ["address"] = new Dictionary + { + ["zip"] = "85900" + } + }, + ["items"] = new Dictionary[] + { + new Dictionary + { + ["product"] = new Dictionary + { + ["description"] = "Ukelele", + ["product_key"] = "60131324", + ["price"] = 345.60 + } + } + }, + ["payment_form"] = Facturapi.PaymentForm.DINERO_ELECTRONICO, + ["folio_number"] = 914, + ["series"] = "F" + }); + // Save PDF stream to a file + var file = new System.IO.FileStream("invoice_preview.pdf", System.IO.FileMode.Create, System.IO.FileAccess.Write); + pdfStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | @@ -4565,7 +4425,9 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = facturapi.invoices().updateDraft("inv_123", Map.of( + var pdf = facturapi.invoices().previewPdf( + Map.of( + "customer", "cus_123", "items", List.of( Map.of( "quantity", 1, @@ -4576,16 +4438,31 @@ paths: - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->updateDraft("58e93bd8e86eb318b019743d", [ - "payment_form" => \Facturapi\PaymentForm::EFECTIVO + $pdfBytes = $facturapi->Invoices->previewPdf([ + "customer" => [ + "legal_name" => "Dunder Mifflin", + "email" => "email@example.com", + "tax_id" => "ABC101010111", + "tax_system" => "601", + "address" => [ + "zip" => "85900" + ] + ], + "items" => [ + [ + "quantity" => 2, + "product" => [ + "description" => "Ukelele", + "product_key" => "60131324", + "price" => 345.60, + "sku" => "ABC4567" + ] + ] + ], + "payment_form" => \Facturapi\PaymentForm::EFECTIVO, + "folio_number" => 914, + "series" => "F" ]); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID del objeto a editar requestBody: $ref: "#/components/requestBodies/InvoiceEdit" security: @@ -4593,11 +4470,12 @@ paths: - "SecretTestKey": [] responses: "200": - description: Objeto `Invoice` editado correctamente + description: El archivo PDF de la factura content: - application/json: + application/pdf: schema: - $ref: "#/components/schemas/InvoiceDraft" + type: string + format: binary "400": $ref: "#/components/responses/BadRequest" "401": @@ -4606,198 +4484,169 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - delete: - operationId: cancelInvoice + /invoices/preview/pdf/download-url: + post: + operationId: previewInvoicePdfUrl tags: - invoice - summary: Cancelar factura - description: | - 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. + summary: Obtener URL del preview PDF de factura + description: Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura sin timbrar. x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d?motive=02 \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X DELETE - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' + import Facturapi from 'facturapi'; const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.cancel( - '58e93bd8e86eb318b019743d', - { motive: '02' } - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.CancelAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["motive"] = "02" - } - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var invoice = facturapi.invoices().cancel( - "inv_123", - Map.of( - "motive", "02" - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $canceled_invoice = $facturapi->Invoices->cancel( - "58e93bd8e86eb318b019743d", - [ - "motive" => "02" - ] - ); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID de la factura a cancelar - - in: query - name: motive - required: true - schema: - type: string - enum: - - "01" - - "02" - - "03" - - "04" - description: | - 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. - - in: query - name: substitution - required: false - schema: - type: string - description: | - ID de la factura que sustituye a la factura que se está cancelando. - Puedes usar el ID de Facturapi o el folio fiscal (UUID). + const download = await facturapi.invoices.previewPdfUrl({ + customer: 'cus_123', + items: [{ product: 'prod_123' }], + payment_form: '06' + }); + console.log(download.url, download.expires_at); + requestBody: + $ref: "#/components/requestBodies/InvoiceEdit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Solicitud de cancelación exitosa + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "409": - $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/copy: - post: - operationId: copyToDraftInvoice + /invoices/{invoice_id}/{format}: + get: + operationId: downloadInvoice tags: - invoice - summary: Copiar a borrador - description: | - Crea una copia en borrador de la factura especificada. + summary: Descargar factura + description: Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/copy \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST + ## Descargar PDF y XML comprimidos en archivo ZIP + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/zip \ + -H "Authorization: Bearer sk_test_API_KEY" + + ## Descargar sólo el PDF + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + + ## Descargar sólo el XML + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/xml \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | + import fs from 'fs'; import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.copyToDraft('58e93bd8e86eb318b019743d'); + + // Descargar PDF y XML comprimidos en archivo ZIP + const zipStream = await facturapi.invoices.downloadZip('58e93bd8e86eb318b019743d'); + const zipFile = fs.createWriteStream('./factura.zip'); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(zipFile); + } + + // Descargar sólo el PDF + const pdfStream = await facturapi.invoices.downloadPdf('58e93bd8e86eb318b019743d'); + const pdfFile = fs.createWriteStream('./factura.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } + + // Descargar sólo el XML + const xmlStream = await facturapi.invoices.downloadXml('58e93bd8e86eb318b019743d'); + const xmlFile = fs.createWriteStream('./factura.xml'); + if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(xmlFile); + } - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Invoice.CopyToDraftAsync("58e93bd8e86eb318b019743d"); + // Descargar PDF y XML comprimidos en archivo ZIP + var zipStream = await facturapi.Invoice.DownloadZipAsync("58e93bd8e86eb318b019743d"); + // Descargar sólo el XML + var xmlStream = await facturapi.Invoice.DownloadXmlAsync("58e93bd8e86eb318b019743d"); + // Descargar sólo el PDF + var pdfStream = await facturapi.Invoice.DownloadPdfAsync("58e93bd8e86eb318b019743d"); + + // Para guardar la descarga en un archivo + var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.zip", FileMode.Create); + zipStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; + import java.io.InputStream; + import java.nio.file.Files; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var draft = facturapi.invoices().copyToDraft( - "inv_123" - ); + try (InputStream zipStream = facturapi.invoices().downloadZip("58e93bd8e86eb318b019743d")) { + Files.copy(zipStream, Path.of("./factura.zip"), StandardCopyOption.REPLACE_EXISTING); + } + + try (InputStream pdfStream = facturapi.invoices().downloadPdf("58e93bd8e86eb318b019743d")) { + Files.copy(pdfStream, Path.of("./factura.pdf"), StandardCopyOption.REPLACE_EXISTING); + } + + try (InputStream xmlStream = facturapi.invoices().downloadXml("58e93bd8e86eb318b019743d")) { + Files.copy(xmlStream, Path.of("./factura.xml"), StandardCopyOption.REPLACE_EXISTING); + } - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->copyToDraft("58e93bd8e86eb318b019743d"); + + // stream containing the PDF and XML as a ZIP file + $zip = $facturapi->Invoices->downloadZip("58e93bd8e86eb318b019743d"); + // stream containing the PDF file + $pdf = $facturapi->Invoices->downloadPdf("58e93bd8e86eb318b019743d"); + // stream containing the XML file + $xml = $facturapi->Invoices->downloadXml("58e93bd8e86eb318b019743d"); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID de la factura a copiar + description: ID del objeto a descargar + - in: path + name: format + schema: + type: string + enum: + - xml + - pdf + - zip + required: true + description: Formato del archivo de descarga security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Nuevo objeto `Invoice` con status `draft`. + description: Archivo del comprobante CFDI en el formato solicitado content: - application/json: + application/octet-stream: schema: - $ref: "#/components/schemas/InvoiceDraft" + type: string + format: binary "400": $ref: "#/components/responses/BadRequest" "401": @@ -4806,93 +4655,72 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/stamp: - post: - operationId: stampDraftInvoice + /invoices/{invoice_id}/download-url/{format}: + get: + operationId: getInvoiceDownloadUrl tags: - invoice - summary: Timbrar borrador de factura + summary: Obtener enlace de descarga description: | - Timbra una factura con status `draft` y la envía al SAT para su validación. + 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. - 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). + El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/stamp \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const stampedInvoice = await facturapi.invoices.stampDraft('58e93bd8e86eb318b019743d'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var stampedInvoice = await facturapi.Invoice.StampDraftAsync("58e93bd8e86eb318b019743d"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; + import Facturapi from 'facturapi'; - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.invoices.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); - var invoice = facturapi.invoices().stampDraft( - "inv_123", - Map.of( - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $stamped_invoice = $facturapi->Invoices->stampDraft("58e93bd8e86eb318b019743d"); + console.log(download.url, download.expires_at); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID del objeto a timbrar - - in: query - name: async + description: ID del objeto a descargar + - in: path + name: format schema: - type: boolean - required: false - description: | - Ú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. + type: string + enum: + - pdf + - xml + - zip + required: true + description: Formato del archivo de descarga security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Objeto `Invoice` timbrado correctamente + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "409": $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/cancellation_receipt/{format}: get: operationId: downloadCancellationReceiptXml @@ -4947,7 +4775,7 @@ paths: // Acuse de factura cancelada xml $facturapi->Invoices->downloadCancellationReceiptXml("58e93bd8e86eb318b019743d"); - + // Acuse de factura cancelada pdf $facturapi->Invoices->downloadCancellationReceiptPdf("58e93bd8e86eb318b019743d"); parameters: @@ -4986,143 +4814,59 @@ paths: "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/payment-summary: + /invoices/{invoice_id}/cancellation_receipt/download-url/{format}: get: - operationId: getInvoicePaymentSummary + operationId: getCancellationReceiptDownloadUrl tags: - invoice - summary: Resumen de pago + summary: Obtener enlace del acuse de cancelación description: | - 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). + 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 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. + El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. x-codeSamples: - lang: Bash label: cURL source: | - curl "https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/payment-summary?amount=100" \ + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/download-url/pdf \ -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); + import Facturapi from 'facturapi'; - const summary = await facturapi.invoices.paymentSummary( - '58e93bd8e86eb318b019743d', - { amount: 100 } + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.invoices.downloadCancellationReceiptPdfUrl( + '58e93bd8e86eb318b019743d' ); - // El resumen va completo como related_document del complemento - const invoice = await facturapi.invoices.create({ - type: 'P', - customer: 'customer_id', - complements: [ - { - type: 'pago', - data: [ - { - payment_form: '28', - related_documents: [summary] - } - ] - } - ] - }); + console.log(download.url, download.expires_at); parameters: - in: path name: invoice_id schema: type: string required: true - description: ID de la factura de ingreso (método de pago PPD) que se desea pagar - - in: query - name: amount + description: ID del objeto a descargar + - in: path + name: format schema: - type: number + type: string + enum: + - xml + - pdf required: true - description: Monto que se paga de esta factura, expresado en la divisa de la factura. No puede exceder el saldo pendiente. + description: Formato del acuse de cancelación security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Resumen del documento relacionado + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. content: application/json: schema: - type: object - properties: - uuid: - type: string - description: UUID de la factura - folio_number: - type: number - description: Folio de la factura. Se omite si la factura no lo tiene registrado. - series: - type: string - nullable: true - description: Serie de la factura - installment: - type: number - description: Número de parcialidad que corresponde a este pago - last_balance: - type: number - description: Saldo pendiente de la factura antes de aplicar este pago - total: - type: number - description: Total de la factura - currency: - type: string - description: Divisa de la factura - amount: - type: number - description: Monto que se paga en esta parcialidad - taxes: - type: array - description: Impuestos de la factura prorrateados al monto pagado - items: - type: object - properties: - base: - type: number - description: Base del impuesto prorrateada al monto pagado - rate: - type: number - description: Tasa o cuota del impuesto - type: - type: string - description: Tipo de impuesto (IVA, ISR, etc.) - factor: - type: string - description: Tipo de factor (Tasa, Exento, etc.) - withholding: - type: boolean - description: Indica si se trata de una retención - example: - uuid: 39c85a3f-275b-4341-b259-e8971d9f8a94 - folio_number: 914 - series: F - installment: 2 - last_balance: 245.6 - total: 345.6 - currency: MXN - amount: 100 - taxes: - - base: 86.21 - rate: 0.16 - type: IVA - factor: Tasa - withholding: false + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": @@ -5133,366 +4877,616 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - - /invoices/{invoice_id}/{format}: - get: - operationId: downloadInvoice + /invoices/{invoice_id}/email: + post: + operationId: sendInvoiceByEmail tags: - invoice - summary: Descargar factura - description: Descarga tu Factura en PDF, XML o ambos en un archivo comprimido ZIP. + summary: Enviar factura por correo electrónico + description: Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. x-codeSamples: - lang: Bash label: cURL source: | - ## Descargar PDF y XML comprimidos en archivo ZIP - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/zip \ - -H "Authorization: Bearer sk_test_API_KEY" - - ## Descargar sólo el PDF - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" + # Enviar al correo del cliente + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/email \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST - ## Descargar sólo el XML - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/xml \ - -H "Authorization: Bearer sk_test_API_KEY" + # Enviar a otro correo + curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/email \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{ + "email": "another_email@example.com" + }' - lang: JavaScript label: Node.js source: | - import fs from 'fs'; import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - // Descargar PDF y XML comprimidos en archivo ZIP - const zipStream = await facturapi.invoices.downloadZip('58e93bd8e86eb318b019743d'); - const zipFile = fs.createWriteStream('./factura.zip'); - zipStream.pipe(zipFile); + // Enviar al correo del cliente + await facturapi.invoices.sendByEmail('58e93bd8e86eb318b019743d'); - // Descargar sólo el PDF - const pdfStream = await facturapi.invoices.downloadPdf('58e93bd8e86eb318b019743d'); - const pdfFile = fs.createWriteStream('./factura.pdf'); - pdfStream.pipe(pdfFile); + // Enviar a otro correo + await facturapi.invoices.sendByEmail( + '58e93bd8e86eb318b019743d', + { email: 'otro@correo.com' } + ); - // Descargar sólo el XML - const xmlStream = await facturapi.invoices.downloadXml('58e93bd8e86eb318b019743d'); - const xmlFile = fs.createWriteStream('./factura.xml'); - xmlStream.pipe(xmlFile); + // Enviar a más de un correo (máx. 10) + await facturapi.invoices.sendByEmail( + '58e93bd8e86eb318b019743d', + { + email: [ + 'primer@correo.com', + 'segundo@correo.com' + ] + } + ); - lang: csharp label: C# source: | - // Descargar PDF y XML comprimidos en archivo ZIP - var zipStream = await facturapi.Invoice.DownloadZipAsync("58e93bd8e86eb318b019743d"); - // Descargar sólo el XML - var xmlStream = await facturapi.Invoice.DownloadXmlAsync("58e93bd8e86eb318b019743d"); - // Descargar sólo el PDF - var pdfStream = await facturapi.Invoice.DownloadPdfAsync("58e93bd8e86eb318b019743d"); + // Enviar al correo del cliente + await facturapi.Invoice.SendByEmailAsync("58e93bd8e86eb318b019743d"); - // Para guardar la descarga en un archivo - var file = new System.IO.FileStream("C:\\route\\to\\save\\invoice.zip", FileMode.Create); - zipStream.CopyTo(file); - file.Close(); + // Enviar a otro correo + await facturapi.Invoice.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = "otro@correo.com" + } + ); + + // Enviar a más de un correo + await facturapi.Invoice.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = new String[] + { + "primer@correo.com", + "segundo@correo.com" + } + } + ); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.io.InputStream; - import java.nio.file.Files; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; + import java.util.List; + import java.util.Map; Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - try (InputStream zipStream = facturapi.invoices().downloadZip("58e93bd8e86eb318b019743d")) { - Files.copy(zipStream, Path.of("./factura.zip"), StandardCopyOption.REPLACE_EXISTING); - } + var response = facturapi.invoices().sendByEmail( + "inv_123", + Map.of( + "to", "cliente@example.com" + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); - try (InputStream pdfStream = facturapi.invoices().downloadPdf("58e93bd8e86eb318b019743d")) { - Files.copy(pdfStream, Path.of("./factura.pdf"), StandardCopyOption.REPLACE_EXISTING); - } + // Enviar al correo del cliente + $facturapi->Invoices->sendByEmail("58e93bd8e86eb318b019743d"); - try (InputStream xmlStream = facturapi.invoices().downloadXml("58e93bd8e86eb318b019743d")) { - Files.copy(xmlStream, Path.of("./factura.xml"), StandardCopyOption.REPLACE_EXISTING); - } + // Enviar a otro correo + $facturapi->Invoices->sendByEmail( + "58e93bd8e86eb318b019743d", + "otro@correo.com" + ); + + // Enviar a más de un correo (máx 10) + $facturapi->Invoices->sendByEmail( + "58e93bd8e86eb318b019743d", + [ + "primer@correo.com", + "segundo@correo.com" + ] + ); + parameters: + - in: path + name: invoice_id + schema: + type: string + required: true + description: ID del objeto a obtener + requestBody: + required: false + content: + application/json: + schema: + type: object + properties: + email: + description: 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. + oneOf: + - type: string + format: email + description: Dirección de correo electrónico + example: otro@correo.com + - type: array + example: ["primer@correo.com", "segundo@correo.com"] + description: Lista de direcciones de correo que recibirán la factura. + maxLength: 10 + items: + type: string + format: email + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Objeto genérico de respuesta + content: + application/json: + schema: + type: object + required: + - ok + properties: + ok: + type: boolean + description: Indica si el correo fue enviado exitosamente + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /invoices/zip-requests: + post: + operationId: createInvoiceZipRequest + tags: + - invoice + summary: Crear o recuperar solicitud de ZIP mensual + description: | + 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. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/invoices/zip-requests \ + -H "Authorization: Bearer sk_live_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "year": 2025, + "month": 3, + "issuer_type": "issuing", + "invoice_types": ["I", "E"] + }' + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequest = await facturapi.invoices.createZipRequest({ + year: 2025, + month: 3, + issuer_type: 'issuing', + invoice_types: ['I', 'E'] + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequest = await facturapi.Invoice.CreateZipRequestAsync( + new Dictionary + { + ["year"] = 2025, + ["month"] = 3, + ["issuer_type"] = "issuing", + ["invoice_types"] = new[] { "I", "E" } + } + ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequest = facturapi.invoices().createZipRequest( + Map.of( + "year", 2025, + "month", 3, + "issuer_type", "issuing", + "invoice_types", List.of("I", "E") + ) + ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequest = $facturapi->Invoices->createZipRequest([ + "year" => 2025, + "month" => 3, + "issuer_type" => "issuing", + "invoice_types" => ["I", "E"] + ]); + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequestCreateInput" + security: + - "SecretLiveKey": [] + responses: + "200": + description: Solicitud de ZIP creada o recuperada correctamente. + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequest" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNoInvoices" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + get: + operationId: listInvoiceZipRequests + tags: + - invoice + summary: Listar solicitudes de ZIP mensual + description: | + 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. - // stream containing the PDF and XML as a ZIP file - $zip = $facturapi->Invoices->downloadZip("58e93bd8e86eb318b019743d"); - // stream containing the PDF file - $pdf = $facturapi->Invoices->downloadPdf("58e93bd8e86eb318b019743d"); - // stream containing the XML file - $xml = $facturapi->Invoices->downloadXml("58e93bd8e86eb318b019743d"); + Este método requiere una llave de API de organización en ambiente Live, una suscripción activa y permiso para leer facturas. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl "https://www.facturapi.io/v2/invoices/zip-requests?year=2025&month=3&status=finished&limit=20&page=1" \ + -H "Authorization: Bearer sk_live_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequests = await facturapi.invoices.listZipRequests({ + year: 2025, + month: 3, + status: 'finished', + limit: 20, + page: 1 + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequests = await facturapi.Invoice.ListZipRequestsAsync( + new Dictionary + { + ["year"] = 2025, + ["month"] = 3, + ["status"] = "finished", + ["limit"] = 20, + ["page"] = 1 + } + ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequests = facturapi.invoices().listZipRequests( + Map.of( + "year", 2025, + "month", 3, + "status", "finished", + "limit", 20, + "page", 1 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequests = $facturapi->Invoices->listZipRequests([ + "year" => 2025, + "month" => 3, + "status" => "finished", + "limit" => 20, + "page" => 1 + ]); + parameters: + - in: query + name: year + schema: + type: integer + minimum: 2000 + maximum: 9999 + description: Año a filtrar. Debe enviarse junto con `month`. + - in: query + name: month + schema: + type: integer + minimum: 1 + maximum: 12 + description: Mes a filtrar. Debe enviarse junto con `year`. + - in: query + name: status + schema: + $ref: "#/components/schemas/InvoiceZipRequestStatus" + description: Status de la solicitud. + - in: query + name: issuer_type + schema: + $ref: "#/components/schemas/IssuingType" + description: Filtra facturas emitidas o recibidas. + - in: query + name: invoice_types + schema: + type: array + uniqueItems: true + items: + $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" + description: Filtra por un tipo de factura o por un arreglo normalizado exacto. + - in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: Página de resultados, empezando en 1. + - $ref: "#/components/parameters/SearchLimit" + security: + - "SecretLiveKey": [] + responses: + "200": + description: Resultado paginado de solicitudes de ZIP. + content: + application/json: + schema: + $ref: "#/components/schemas/InvoiceZipRequestSearchResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /invoices/zip-requests/{id}: + get: + operationId: retrieveInvoiceZipRequest + tags: + - invoice + summary: Recuperar solicitud de ZIP mensual + description: | + 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. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000 \ + -H "Authorization: Bearer sk_live_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipRequest = await facturapi.invoices.retrieveZipRequest( + '66b0f0000000000000000000' + ); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipRequest = await facturapi.Invoice.RetrieveZipRequestAsync( + "66b0f0000000000000000000" + ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + var zipRequest = facturapi.invoices().retrieveZipRequest( + "66b0f0000000000000000000" + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_live_API_KEY"); + $zipRequest = $facturapi->Invoices->retrieveZipRequest( + "66b0f0000000000000000000" + ); parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID del objeto a descargar - - in: path - name: format - schema: - type: string - enum: - - xml - - pdf - - zip - required: true - description: Formato del archivo de descarga + - $ref: "#/components/parameters/InvoiceZipRequestId" security: - "SecretLiveKey": [] - - "SecretTestKey": [] responses: "200": - description: Archivo del comprobante CFDI en el formato solicitado + description: Solicitud de ZIP recuperada correctamente. content: - application/octet-stream: + application/json: schema: - type: string - format: binary + $ref: "#/components/schemas/InvoiceZipRequest" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/email: - post: - operationId: sendInvoiceByEmail + /invoices/zip-requests/{id}/zip: + get: + operationId: downloadInvoiceZipRequest tags: - invoice - summary: Enviar factura por correo electrónico - description: Envía un correo electrónico a la dirección de tu cliente, con los archivos XML y PDF adjuntos al mensaje. + summary: Descargar ZIP mensual + description: | + 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. x-codeSamples: - lang: Bash label: cURL source: | - # Enviar al correo del cliente - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/email \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST - - # Enviar a otro correo - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/email \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST \ - -H "Content-Type: application/json" \ - -d '{ - "email": "another_email@example.com" - }' + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/zip \ + -H "Authorization: Bearer sk_live_API_KEY" \ + --output 2025-03.zip - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - // Enviar al correo del cliente - await facturapi.invoices.sendByEmail('58e93bd8e86eb318b019743d'); - - // Enviar a otro correo - await facturapi.invoices.sendByEmail( - '58e93bd8e86eb318b019743d', - { email: 'otro@correo.com' } - ); + import fs from 'fs'; + import Facturapi from 'facturapi'; - // Enviar a más de un correo (máx. 10) - await facturapi.invoices.sendByEmail( - '58e93bd8e86eb318b019743d', - { - email: [ - 'primer@correo.com', - 'segundo@correo.com' - ] - } + const facturapi = new Facturapi('sk_live_API_KEY'); + const zipStream = await facturapi.invoices.downloadZipRequest( + '66b0f0000000000000000000' ); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(fs.createWriteStream('./2025-03.zip')); + } - lang: csharp label: C# source: | - // Enviar al correo del cliente - await facturapi.Invoice.SendByEmailAsync("58e93bd8e86eb318b019743d"); - - // Enviar a otro correo - await facturapi.Invoice.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = "otro@correo.com" - } - ); - - // Enviar a más de un correo - await facturapi.Invoice.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = new String[] - { - "primer@correo.com", - "segundo@correo.com" - } - } + var facturapi = new FacturapiClient("sk_live_API_KEY"); + var zipStream = await facturapi.Invoice.DownloadZipRequestAsync( + "66b0f0000000000000000000" ); + await using var file = File.Create("2025-03.zip"); + await zipStream.CopyToAsync(file); - lang: Java label: Java source: | import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + import java.io.InputStream; + import java.nio.file.Files; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; - var response = facturapi.invoices().sendByEmail( - "inv_123", - Map.of( - "to", "cliente@example.com" - ) - ); + Facturapi facturapi = new Facturapi("sk_live_API_KEY"); + try (InputStream zipStream = facturapi.invoices().downloadZipRequest( + "66b0f0000000000000000000" + )) { + Files.copy(zipStream, Path.of("./2025-03.zip"), StandardCopyOption.REPLACE_EXISTING); + } - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // Enviar al correo del cliente - $facturapi->Invoices->sendByEmail("58e93bd8e86eb318b019743d"); - - // Enviar a otro correo - $facturapi->Invoices->sendByEmail( - "58e93bd8e86eb318b019743d", - "otro@correo.com" - ); - - // Enviar a más de un correo (máx 10) - $facturapi->Invoices->sendByEmail( - "58e93bd8e86eb318b019743d", - [ - "primer@correo.com", - "segundo@correo.com" - ] + $facturapi = new Facturapi("sk_live_API_KEY"); + $zip = $facturapi->Invoices->downloadZipRequest( + "66b0f0000000000000000000" ); + file_put_contents("2025-03.zip", $zip); parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID del objeto a obtener - requestBody: - required: false - content: - application/json: - schema: - type: object - properties: - email: - description: 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. - oneOf: - - type: string - format: email - description: Dirección de correo electrónico - example: otro@correo.com - - type: array - example: ["primer@correo.com", "segundo@correo.com"] - description: Lista de direcciones de correo que recibirán la factura. - maxLength: 10 - items: - type: string - format: email + - $ref: "#/components/parameters/InvoiceZipRequestId" security: - "SecretLiveKey": [] - - "SecretTestKey": [] responses: "200": - description: Objeto genérico de respuesta + description: Archivo ZIP generado. + headers: + Content-Disposition: + description: Nombre sugerido con formato `attachment; filename="YYYY-MM.zip"`. + schema: + type: string content: - application/json: + application/zip: schema: - type: object - required: - - ok - properties: - ok: - type: boolean - description: Indica si el correo fue enviado exitosamente + type: string + format: binary "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/InvoiceZipRequestNotReady" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/status: - put: - operationId: updateInvoiceStatus + /invoices/zip-requests/{id}/download-url: + get: + operationId: getInvoiceZipRequestDownloadUrl tags: - invoice - summary: | - Actualizar status de factura + summary: Obtener URL de descarga del ZIP mensual description: | - Consulta el status de una factura timbrada en el SAT y actualiza el objeto invoice - con La información más reciente. + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/status \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X PUT + curl https://www.facturapi.io/v2/invoices/zip-requests/66b0f0000000000000000000/download-url \ + -H "Authorization: Bearer sk_live_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.invoices.updateStatus('58e93bd8e86eb318b019743d'); - - lang: csharp - label: C# - source: | - var facturapi = new Facturapi - var invoice = await facturapi.Invoice.UpdateStatusAsync("58e93bd8e86eb318b019743d"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + import Facturapi from 'facturapi'; - var invoice = facturapi.invoices().updateStatus( - "inv_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Invoices->updateStatus("58e93bd8e86eb318b019743d"); + const facturapi = new Facturapi('sk_live_API_KEY'); + const download = await facturapi.invoices.downloadZipRequestUrl( + '66b0f0000000000000000000' + ); + + console.log(download.url, download.expires_at); parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID del objeto invoice a actualizar + - $ref: "#/components/parameters/InvoiceZipRequestId" security: - "SecretLiveKey": [] - - "SecretTestKey": [] responses: "200": - description: Objeto `Invoice` actualizado + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. content: application/json: schema: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/SignedDownloadUrl" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "402": + $ref: "#/components/responses/InvoiceZipRequestAccessRequired" + "404": + $ref: "#/components/responses/InvoiceZipRequestNotFound" + "409": + $ref: "#/components/responses/InvoiceZipRequestNotReady" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts: post: operationId: createReceipt @@ -5650,11 +5644,11 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // Todos los recibos de la organización - const receiptSearch = await facturapi.receipts.list(); + const receiptSearch1 = await facturapi.receipts.list(); // Página 3 de los resultados de búsqueda de texto libre // de recibos creados entre 2017 y 2019 - const receiptSearch = await facturapi.receipts.list({ + const receiptSearch2 = await facturapi.receipts.list({ q: 'Aspiradora Robot', date: { gte: new Date('2017-01-01T00:00:00.000Z'), @@ -5882,13 +5876,13 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // Asignar un cliente existente por ID - const receipt = await facturapi.receipts.assignCustomer( + const receipt = await facturapi.receipts.updateCustomer( '58e93bd8e86eb318b019743d', { customer: '58e93bd8e86eb318b0197456' } ); // O crear el cliente desde payload y asignarlo al recibo - const receiptWithNewCustomer = await facturapi.receipts.assignCustomer( + const receiptWithNewCustomer = await facturapi.receipts.updateCustomer( '58e93bd8e86eb318b019743d', { customer: { @@ -6035,257 +6029,24 @@ paths: - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $facturapi->Receipts->cancel("5ebd8e56f5687a013ca0df46"); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID del recibo a cancelar - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Objeto 'Receipt' cancelado exitosamente - content: - application/json: - schema: - $ref: "#/components/schemas/Receipt" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/pdf: - get: - operationId: downloadReceiptPdf - tags: - - receipt - summary: Descargar PDF - description: Descarga el recibo digital en formato PDF. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import fs from 'fs'; - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - // Descargar recibo en formato PDF - const pdfStream = await facturapi.receipts.downloadPdf('58e93bd8e86eb318b019743d'); - const pdfFile = fs.createWriteStream('./recibo.pdf'); - pdfStream.pipe(pdfFile); - - lang: csharp - label: C# - source: | - // Descargar recibo en formato PDF - var pdfStream = await facturapi.Receipt.DownloadPdfAsync("58e93bd8e86eb318b019743d"); - - // Para guardar la descarga en un archivo - var file = new System.IO.FileStream("C:\\route\\to\\save\\receipt.pdf", FileMode.Create); - pdfStream.CopyTo(file); - file.Close(); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - byte[] pdf = facturapi.receipts().downloadPdf( - "rec_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // stream containing the PDF file - $pdf = $facturapi->Receipts->downloadPdf("58e93bd8e86eb318b019743d"); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID del objeto a descargar - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Archivo del recibo digital en formato PDF - content: - application/octet-stream: - schema: - type: string - format: binary - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/email: - post: - operationId: sendReceiptByEmail - tags: - - receipt - summary: Enviar recibo por correo electrónico - description: | - 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. - x-codeSamples: - - lang: Bash - label: cURL - source: | - # Enviar recibo por correo electrónico - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/email \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -X POST \ - -H "Content-Type: application/json" \ - -d '{ - "email": "another_email@example.com" - }' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - // Enviar recibo por correo electrónico - await facturapi.receipts.sendByEmail( - '58e93bd8e86eb318b019743d', - { email: 'ejemplo@correo.com' } - ); - - // Enviar a más de un correo (máx. 10) - await facturapi.receipts.sendByEmail( - '58e93bd8e86eb318b019743d', - { - email: [ - 'primer@correo.com', - 'segundo@correo.com' - ] - } - ); - - lang: csharp - label: C# - source: | - // Enviar recibo por correo electrónico - await facturapi.Receipt.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = "ejemplo@correo.com" - } - ); - - // Enviar a más de un correo - await facturapi.Receipt.SendByEmailAsync( - "58e93bd8e86eb318b019743d", - new Dictionary - { - ["email"] = new String[] - { - "primer@correo.com", - "segundo@correo.com" - } - } - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var response = facturapi.receipts().sendByEmail( - "rec_123", - Map.of( - "to", "cliente@example.com" - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - // Enviar recibo por correo electrónico - $facturapi->Receipts->sendByEmail( - "58e93bd8e86eb318b019743d", - "ejemplo@correo.com" - ); - - // Enviar a más de un correo (máx 10) - $facturapi->Receipts->sendByEmail( - "58e93bd8e86eb318b019743d", - [ - "primer@correo.com", - "segundo@correo.com" - ] - ); - parameters: - - in: path - name: receipt_id - schema: - type: string - required: true - description: ID del objeto a obtener - requestBody: - required: false - content: - application/json: - schema: - type: object - required: - - email - properties: - email: - description: Dirección de correo electrónico a enviar el recibo digital. - oneOf: - - type: string - format: email - description: Dirección de correo electrónico - example: otro@correo.com - - type: array - example: ["primer@correo.com", "segundo@correo.com"] - description: Lista de direcciones de correo que recibirán el recibo digital. - maxLength: 10 - items: - type: string - format: email + $facturapi->Receipts->cancel("5ebd8e56f5687a013ca0df46"); + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID del recibo a cancelar security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Objeto genérico de respuesta + description: Objeto 'Receipt' cancelado exitosamente content: application/json: schema: - type: object - required: - - ok - properties: - ok: - type: boolean - description: Indica si el correo fue enviado exitosamente + $ref: "#/components/schemas/Receipt" "400": $ref: "#/components/responses/BadRequest" "401": @@ -6294,7 +6055,6 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/invoice: post: operationId: invoiceReceipt @@ -6571,43 +6331,295 @@ paths: label: Node.js source: | import Facturapi from 'facturapi' - import fs from 'fs' + import fs from 'fs' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const pdfStream = await facturapi.receipts.previewToInvoicePdf({ + keys: ['ticket_1001', 'ticket_1002'], + customer: { + legal_name: 'Dunder Mifflin', + tax_id: 'ABC101010111', + tax_system: '601', + address: { + zip: '85900' + } + }, + use: 'G03' + }); + + const file = fs.createWriteStream('to_invoice_preview.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(file); + } + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var pdfStream = await facturapi.Receipt.PreviewToInvoicePdfAsync(new Dictionary + { + ["keys"] = new[] { "ticket_1001", "ticket_1002" }, + ["customer"] = new Dictionary + { + ["legal_name"] = "Dunder Mifflin", + ["tax_id"] = "ABC101010111", + ["tax_system"] = "601", + ["address"] = new Dictionary + { + ["zip"] = "85900" + } + }, + ["use"] = "G03" + }); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var pdf = facturapi.receipts().previewToInvoicePdf( + Map.of( + "keys", List.of("ticket_1001", "ticket_1002"), + "customer", Map.of( + "legal_name", "Dunder Mifflin", + "tax_id", "ABC101010111", + "tax_system", "601", + "address", Map.of("zip", "85900") + ), + "use", "G03" + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $pdfBytes = $facturapi->Receipts->previewToInvoicePdf([ + "keys" => ["ticket_1001", "ticket_1002"], + "customer" => [ + "legal_name" => "Dunder Mifflin", + "tax_id" => "ABC101010111", + "tax_system" => "601", + "address" => [ + "zip" => "85900" + ] + ], + "use" => "G03" + ]); + requestBody: + $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Contenido binario del PDF + content: + application/pdf: + schema: + type: string + format: binary + "204": + description: No se encontraron recibos elegibles para las keys enviadas + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "500": + $ref: "#/components/responses/UnexpectedError" + /receipts/to-invoice/preview/download-url: + post: + operationId: previewToInvoiceFromReceiptsUrl + tags: + - receipt + summary: Obtener URL del preview de factura de recibos + description: Devuelve un objeto con los metadatos del archivo y una URL temporal para el preview PDF de una factura construida con los recibos seleccionados. + x-codeSamples: + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + const facturapi = new Facturapi('sk_test_API_KEY'); + + const download = await facturapi.receipts.previewToInvoicePdfUrl({ + keys: ['ticket_1001', 'ticket_1002'], + customer: 'cus_123', + use: 'G03' + }); + console.log(download.url, download.expires_at); + requestBody: + $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. + content: + application/json: + schema: + $ref: "#/components/schemas/SignedDownloadUrl" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /receipts/global-invoice: + post: + operationId: createGlobalInvoice + tags: + - receipt + summary: Crear factura global + description: | + 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`. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/global-invoice \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "from": "2021-01-01T00:00:00.000Z", + "to": "2021-01-31T23:59:59.999Z", + "periodicity": "month", + "months": "01", + "folio_number": 1234, + "series": "G", + "limit_to_max_receipts": true + }' + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const invoice = await facturapi.receipts.createGlobalInvoice({ + from: '2021-01-01T00:00:00.000Z', + to: '2021-01-31T23:59:59.999Z', + periodicity: 'month', + months: '01', + folio_number: 1234, + series: 'G', + limit_to_max_receipts: true + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + var invoice = await facturapi.Receipt.CreateGlobalInvoiceAsync(new Dictionary + { + ["from"] = "2021-01-01T00:00:00.000Z", + ["to"] = "2021-01-31T23:59:59.999Z", + ["periodicity"] = "month", + ["months"] = "01", + ["folio_number"] = 1234, + ["series"] = "G" + }); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var invoice = facturapi.receipts().createGlobalInvoice( + Map.of( + "from", "2021-01-01T00:00:00.000Z", + "to", "2021-01-31T23:59:59.999Z", + "periodicity", "month", + "months", "01" + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $invoice = $facturapi->Receipts->createGlobalInvoice([ + "from" => "2021-01-01T00:00:00.000Z", + "to" => "2021-01-31T23:59:59.999Z", + "periodicity" => "month", + "months" => "01", + "folio_number" => 1234, + "series" => "G" + ]); + requestBody: + $ref: "#/components/requestBodies/ReceiptCreateGlobalInvoice" + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Nuevo objeto `Invoice` creado, o `null` si no hay recibos abiertos en el periodo + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/Invoice" + - type: "null" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + + /receipts/{receipt_id}/pdf: + get: + operationId: downloadReceiptPdf + tags: + - receipt + summary: Descargar PDF + description: Descarga el recibo digital en formato PDF. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import fs from 'fs'; + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const pdfStream = await facturapi.receipts.previewToInvoicePdf({ - keys: ['ticket_1001', 'ticket_1002'], - customer: { - legal_name: 'Dunder Mifflin', - tax_id: 'ABC101010111', - tax_system: '601', - address: { - zip: '85900' - } - }, - use: 'G03' - }); - - const file = fs.createWriteStream('to_invoice_preview.pdf'); - pdfStream.pipe(file); + // Descargar recibo en formato PDF + const pdfStream = await facturapi.receipts.downloadPdf('58e93bd8e86eb318b019743d'); + const pdfFile = fs.createWriteStream('./recibo.pdf'); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var pdfStream = await facturapi.Receipt.PreviewToInvoicePdfAsync(new Dictionary - { - ["keys"] = new[] { "ticket_1001", "ticket_1002" }, - ["customer"] = new Dictionary - { - ["legal_name"] = "Dunder Mifflin", - ["tax_id"] = "ABC101010111", - ["tax_system"] = "601", - ["address"] = new Dictionary - { - ["zip"] = "85900" - } - }, - ["use"] = "G03" - }); + // Descargar recibo en formato PDF + var pdfStream = await facturapi.Receipt.DownloadPdfAsync("58e93bd8e86eb318b019743d"); + + // Para guardar la descarga en un archivo + var file = new System.IO.FileStream("C:\\route\\to\\save\\receipt.pdf", FileMode.Create); + pdfStream.CopyTo(file); + file.Close(); - lang: Java label: Java source: | @@ -6616,81 +6628,81 @@ paths: import java.util.Map; Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var pdf = facturapi.receipts().previewToInvoicePdf( - Map.of( - "keys", List.of("ticket_1001", "ticket_1002"), - "customer", Map.of( - "legal_name", "Dunder Mifflin", - "tax_id", "ABC101010111", - "tax_system", "601", - "address", Map.of("zip", "85900") - ), - "use", "G03" - ) - ); + byte[] pdf = facturapi.receipts().downloadPdf( + "rec_123" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $pdfBytes = $facturapi->Receipts->previewToInvoicePdf([ - "keys" => ["ticket_1001", "ticket_1002"], - "customer" => [ - "legal_name" => "Dunder Mifflin", - "tax_id" => "ABC101010111", - "tax_system" => "601", - "address" => [ - "zip" => "85900" - ] - ], - "use" => "G03" - ]); - requestBody: - $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + // stream containing the PDF file + $pdf = $facturapi->Receipts->downloadPdf("58e93bd8e86eb318b019743d"); + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID del objeto a descargar security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Contenido binario del PDF + description: Archivo del recibo digital en formato PDF content: - application/pdf: + application/octet-stream: schema: type: string format: binary - "204": - description: No se encontraron recibos elegibles para las keys enviadas "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "429": + $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/to-invoice/preview/download-url: - post: - operationId: previewToInvoiceFromReceiptsUrl + /receipts/{receipt_id}/download-url/pdf: + get: + operationId: getReceiptDownloadUrl tags: - receipt - summary: Obtener URL del preview de factura de recibos - description: Devuelve una URL temporal para el preview PDF de una factura construida con los recibos seleccionados. + summary: Obtener enlace de descarga + description: | + 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. x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - const download = await facturapi.receipts.previewToInvoicePdfUrl({ - keys: ['ticket_1001', 'ticket_1002'], - customer: 'cus_123', - use: 'G03' - }); + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.receipts.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); + console.log(download.url, download.expires_at); - requestBody: - $ref: "#/components/requestBodies/ReceiptPreviewToInvoice" + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID del objeto a descargar security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: URL temporal de descarga para el preview PDF. + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. content: application/json: schema: @@ -6705,69 +6717,75 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/global-invoice: + /receipts/{receipt_id}/email: post: - operationId: createGlobalInvoice + operationId: sendReceiptByEmail tags: - receipt - summary: Crear factura global + summary: Enviar recibo por correo electrónico description: | - 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"`. + Envía un correo electrónico a la dirección de tu cliente. - 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`. + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/receipts/global-invoice \ + # Enviar recibo por correo electrónico + curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/email \ -H "Authorization: Bearer sk_test_API_KEY" \ + -X POST \ -H "Content-Type: application/json" \ -d '{ - "from": "2021-01-01T05:00:00.000Z", - "to": "2021-01-31T04:59:59.999Z", - "periodicity": "month", - "months": "01", - "year": 2021, - "folio_number": 1234, - "series": "G", - "limit_to_max_receipts": true - }' + "email": "another_email@example.com" + }' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const invoice = await facturapi.receipts.createGlobalInvoice({ - from: '2020-12-01T05:00:00.000Z', - to: '2020-12-31T04:59:59.999Z', - periodicity: 'month', - months: '01', - year: 2021, - folio_number: 1234, - series: 'G', - limit_to_max_receipts: true - }); + // Enviar recibo por correo electrónico + await facturapi.receipts.sendByEmail( + '58e93bd8e86eb318b019743d', + { email: 'ejemplo@correo.com' } + ); + + // Enviar a más de un correo (máx. 10) + await facturapi.receipts.sendByEmail( + '58e93bd8e86eb318b019743d', + { + email: [ + 'primer@correo.com', + 'segundo@correo.com' + ] + } + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var invoice = await facturapi.Receipt.CreateGlobalInvoiceAsync(new Dictionary - { - ["from"] = "2020-12-01T05:00:00.000Z", - ["to"] = "2020-12-31T04:59:59.999Z", - ["periodicity"] = "month", - ["months"] = "01", - ["year"] = 2021, - ["folio_number"] = 1234, - ["series"] = "G" - }); + // Enviar recibo por correo electrónico + await facturapi.Receipt.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = "ejemplo@correo.com" + } + ); + + // Enviar a más de un correo + await facturapi.Receipt.SendByEmailAsync( + "58e93bd8e86eb318b019743d", + new Dictionary + { + ["email"] = new String[] + { + "primer@correo.com", + "segundo@correo.com" + } + } + ); - lang: Java label: Java source: | @@ -6777,45 +6795,80 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var invoice = facturapi.receipts().createGlobalInvoice( + var response = facturapi.receipts().sendByEmail( + "rec_123", Map.of( - "month", 5, - "year", 2024 + "to", "cliente@example.com" ) ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $invoice = $facturapi->Receipts->createGlobalInvoice([ - "from" => "2020-12-01T05:00:00.000Z", - "to" => "2020-12-31T04:59:59.999Z", - "periodicity" => "month", - "months" => "01", - "year" => 2021, - "folio_number" => 1234, - "series" => "G" - ]); + // Enviar recibo por correo electrónico + $facturapi->Receipts->sendByEmail( + "58e93bd8e86eb318b019743d", + "ejemplo@correo.com" + ); + + // Enviar a más de un correo (máx 10) + $facturapi->Receipts->sendByEmail( + "58e93bd8e86eb318b019743d", + [ + "primer@correo.com", + "segundo@correo.com" + ] + ); + parameters: + - in: path + name: receipt_id + schema: + type: string + required: true + description: ID del objeto a obtener requestBody: - $ref: "#/components/requestBodies/ReceiptCreateGlobalInvoice" + required: false + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + description: Dirección de correo electrónico a enviar el recibo digital. + oneOf: + - type: string + format: email + description: Dirección de correo electrónico + example: otro@correo.com + - type: array + example: ["primer@correo.com", "segundo@correo.com"] + description: Lista de direcciones de correo que recibirán el recibo digital. + maxLength: 10 + items: + type: string + format: email security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Nuevo objeto `Invoice` creado, o `null` si no hay recibos abiertos en el periodo + description: Objeto genérico de respuesta content: application/json: schema: - oneOf: - - $ref: "#/components/schemas/Invoice" - - type: "null" + type: object + required: + - ok + properties: + ok: + type: boolean + description: Indica si el correo fue enviado exitosamente "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -6855,7 +6908,8 @@ paths: "imp_retenidos": [ { "monto_ret": 40, - "base_ret": 250 + "base_ret": 250, + "tipo_pago_ret": "04" } ] } @@ -6879,7 +6933,8 @@ paths: imp_retenidos: [ { monto_ret: 40, - base_ret: 250 + base_ret: 250, + tipo_pago_ret: "04" } ] } @@ -6906,9 +6961,9 @@ paths: { new Dictionary { - ["] ["monto_ret"] = 40, - ["base_ret"] = 250 + ["base_ret"] = 250, + ["tipo_pago_ret"] = "04" } } } @@ -6924,16 +6979,19 @@ paths: var retention = facturapi.retentions().create( Map.of( - "receiver", Map.of( - "name", "Cliente ejemplo" - ), - "items", List.of( - Map.of( - "quantity", 1, - "product", "prod_123" - ) - ) - )); + "customer", "58e93bd8e86eb318b0197456", + "cve_retenc", "26", + "periodo", Map.of("mes_ini", 1, "mes_fin", 12, "ejerc", 2020), + "totales", Map.of( + "monto_tot_operacion", 244.654321, + "monto_tot_exent", 145.123456, + "imp_retenidos", List.of(Map.of( + "monto_ret", 40, + "base_ret", 250, + "tipo_pago_ret", "04" + )) + ) + )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); @@ -6952,7 +7010,8 @@ paths: [ "impuesto" => "ISR", "monto_ret" => 40, - "base_ret" => 250 + "base_ret" => 250, + "tipo_pago_ret" => "04" ] ] ] @@ -7012,16 +7071,16 @@ paths: const facturapi = new Facturapi('sk_test_API_KEY'); // Todas las retenciones de la organización - const retentionSearch = await facturapi.retentions.list(); + const retentionSearch1 = await facturapi.retentions.list(); // Todas las retenciones emitidas para cierto cliente - const retentionSearch = await facturapi.retentions.list({ + const retentionSearch2 = await facturapi.retentions.list({ customer: '590ce6c56d04f840aa8438af' }); // Página 3 de los resultados de búsqueda de texto libre // de retenciones emitidas entre 2017 y 2019 - const retentionSearch = await facturapi.retentions.list({ + const retentionSearch3 = await facturapi.retentions.list({ q: 'John Doe', date: { gte: new Date('2017-01-01T00:00:00.000Z'), @@ -7121,11 +7180,13 @@ paths: items: type: string enum: + - all - draft - pending - valid - canceled - description: Filtrar por uno o más estados de retención. + - failed + description: "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." - $ref: "#/components/parameters/SearchDate" - $ref: "#/components/parameters/SearchPage" - $ref: "#/components/parameters/SearchLimit" @@ -7313,7 +7374,7 @@ paths: description: | Realiza una solicitud de cancelación de retención ante el SAT. - A diferencia de las facturas comúnes, la cancelación de la retención es inmediata y no requiere autorización de parte del receptor. + 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. @@ -7372,14 +7433,14 @@ paths: description: ID de la retención a cancelar - in: query name: motive - required: true + required: false schema: type: string enum: - - "01" - - "02" - - "03" - - "04" + - '01' + - '02' + - '03' + - '04' description: | Clave que representa el motivo de la cancelación de la retención. Requerido para retenciones que no son borrador. @@ -7401,6 +7462,7 @@ paths: description: | 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. security: - "SecretLiveKey": [] - "SecretTestKey": [] @@ -7585,17 +7647,23 @@ paths: // Descargar PDF y XML comprimidos en archivo ZIP const zipStream = await facturapi.retentions.downloadZip('58e93bd8e86eb318b019743d'); const zipFile = fs.createWriteStream('./retencion.zip'); - zipStream.pipe(zipFile); + if ('pipe' in zipStream && typeof zipStream.pipe === 'function') { + zipStream.pipe(zipFile); + } // Descargar sólo el PDF const pdfStream = await facturapi.retentions.downloadPdf('58e93bd8e86eb318b019743d'); const pdfFile = fs.createWriteStream('./retencion.pdf'); - pdfStream.pipe(pdfFile); + if ('pipe' in pdfStream && typeof pdfStream.pipe === 'function') { + pdfStream.pipe(pdfFile); + } // Descargar sólo el XML const xmlStream = await facturapi.retentions.downloadXml('58e93bd8e86eb318b019743d'); const xmlFile = fs.createWriteStream('./retencion.xml'); - xmlStream.pipe(xmlFile); + if ('pipe' in xmlStream && typeof xmlStream.pipe === 'function') { + xmlStream.pipe(xmlFile); + } - lang: csharp label: C# source: | @@ -7667,6 +7735,72 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" + /retentions/{retention_id}/download-url/{format}: + get: + operationId: getRetentionDownloadUrl + tags: + - retention + summary: Obtener enlace de descarga + description: | + 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. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/retentions/58e93bd8e86eb318b019743d/download-url/pdf \ + -H "Authorization: Bearer sk_test_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi'; + + const facturapi = new Facturapi('sk_test_API_KEY'); + const download = await facturapi.retentions.downloadPdfUrl( + '58e93bd8e86eb318b019743d' + ); + + console.log(download.url, download.expires_at); + parameters: + - in: path + name: retention_id + schema: + type: string + required: true + description: ID del objeto a descargar + - in: path + name: format + schema: + type: string + enum: + - pdf + - xml + - zip + required: true + description: Formato del archivo de descarga + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Objeto con una URL temporal de descarga, su fecha de expiración, el tipo de contenido y el nombre del archivo. + content: + application/json: + schema: + $ref: "#/components/schemas/SignedDownloadUrl" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "409": + $ref: "#/components/responses/Conflict" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" /retentions/{retention_id}/email: post: operationId: sendRetentionByEmail @@ -7845,8 +7979,8 @@ paths: 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 @@ -7932,27 +8066,170 @@ paths: operationId: listOrganizations tags: - organization - summary: Listar organizaciones - description: Regresa una lista paginada de todas las organizationes registradas bajo tu cuenta, o realiza una búsqueda de acuerdo a parámetros. + summary: Listar organizaciones + description: Regresa una lista paginada de todas las organizationes registradas bajo tu cuenta, o realiza una búsqueda de acuerdo a parámetros. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/organizations \ + -H "Authorization: Bearer sk_user_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const organizationResults = await facturapi.organizations.list(); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Organization.ListAsync(); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var searchResult = facturapi.organizations().list( + Map.of( + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $organizations = $facturapi->Organizations->all() + parameters: + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q + schema: + type: string + description: Consulta. Texto a buscar en `name` (nombre comercial), `legal_name` (nombre fiscal) o en `tax_id` (RFC). + - $ref: "#/components/parameters/SearchDate" + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" + security: + - "SecretUserKey": [] + responses: + "200": + description: Resultado de la búsqueda + content: + application/json: + schema: + $ref: "#/components/schemas/OrganizationSearchResult" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /organizations/me: + get: + operationId: meOrganization + tags: + - organization + summary: Detalle de organización + description: | + Retorna el detalle de la organización actualmente autenticada. + x-codeSamples: + - lang: Bash + label: cURL + source: | + curl https://www.facturapi.io/v2/organizations/me \ + -H "Authorization: Bearer sk_user_API_KEY" + - lang: JavaScript + label: Node.js + source: | + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const organizationResults = await facturapi.organizations.me(); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Organization.MeAsync(); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; + + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var organization = facturapi.organizations().me( + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $organizations = $facturapi->Organizations->me() + security: + - "SecretLiveKey": [] + - "SecretTestKey": [] + responses: + "200": + description: Objeto `Organization` + content: + application/json: + schema: + $ref: "#/components/schemas/Organization" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" + "429": + $ref: "#/components/responses/RateLimited" + "500": + $ref: "#/components/responses/UnexpectedError" + /organizations/{organization_id}: + get: + operationId: getOrganization + tags: + - organization + summary: Obtener organización por ID + description: Regresa el objeto 'Organization' relacionado al `id` especificado. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/organizations \ + curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ -H "Authorization: Bearer sk_user_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - const organizationResults = await facturapi.organizations.list(); + const facturapi = new Facturapi('sk_user_API_KEY'); + const organization = await facturapi.organizations.retrieve( + '5a2a307be93a2f00129ea035' + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Organization.ListAsync(); + var facturapi = new FacturapiClient("sk_user_API_KEY"); + var organization = await facturapi.Organization.RetrieveAsync( + "5a2a307be93a2f00129ea035" + ); - lang: Java label: Java source: | @@ -7962,76 +8239,70 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var searchResult = facturapi.organizations().list( - Map.of( - "page", 0, - "limit", 10 - ) + var organization = facturapi.organizations().retrieve( + "org_123" ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - $organizations = $facturapi->Organizations->all() + $facturapi = new Facturapi("sk_user_API_KEY"); + $organization = $facturapi->Organizations->retrieve("5a2a307be93a2f00129ea035"); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q + - in: path + name: organization_id schema: type: string - description: Consulta. Texto a buscar en `name` (nombre comercial), `legal_name` (nombre fiscal) o en `tax_id` (RFC). - - $ref: "#/components/parameters/SearchDate" - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + required: true + description: ID de la organización security: + - "SecretLiveKey": [] + - "SecretTestKey": [] - "SecretUserKey": [] responses: "200": - description: Resultado de la búsqueda + description: Objeto `Organization` content: application/json: schema: - $ref: "#/components/schemas/OrganizationSearchResult" + $ref: "#/components/schemas/Organization" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /organizations/me: - get: - operationId: meOrganization + delete: + operationId: deleteOrganization tags: - organization - summary: Detalle de organización + summary: Eliminar organización description: | - Retorna el detalle de la organización actualmente autenticada. + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/organizations/me \ + curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ + -X DELETE \ -H "Authorization: Bearer sk_user_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - - const organizationResults = await facturapi.organizations.me(); + const facturapi = new Facturapi('sk_user_API_KEY'); + const organization = await facturapi.organizations.del( + '5a2a307be93a2f00129ea035' + ); - lang: csharp label: C# source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Organization.MeAsync(); + var facturapi = new FacturapiClient("sk_user_API_KEY"); + var organization = await facturapi.Organization.DeleteAsync( + "5a2a307be93a2f00129ea035" + ); - lang: Java label: Java source: | @@ -8041,19 +8312,27 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var organization = facturapi.organizations().me( + var organization = facturapi.organizations().delete( + "org_123" ); - lang: PHP source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - - $organizations = $facturapi->Organizations->me() + $facturapi = new Facturapi("sk_user_API_KEY"); + $organization = $facturapi->Organizations->delete( + "5a2a307be93a2f00129ea035" + ); + parameters: + - in: path + name: organization_id + schema: + type: string + required: true + description: ID del objeto a eliminar security: - - "SecretLiveKey": [] - - "SecretTestKey": [] + - "SecretUserKey": [] responses: "200": - description: Objeto `Organization` + description: Objeto `Organization` eliminado correctamente content: application/json: schema: @@ -8062,8 +8341,6 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -9035,157 +9312,9 @@ paths: source: | $facturapi = new Facturapi("sk_user_API_KEY"); - $organization = $facturapi->Organizations->updateDomain( - "5a2a307be93a2f00129ea035", - [ "domain" => "empresa-demo" ] - ); - parameters: - - in: path - name: organization_id - schema: - type: string - required: true - description: ID de la organización - requestBody: - $ref: "#/components/requestBodies/OrganizationEditDomain" - security: - - "SecretLiveKey": [] - - "SecretUserKey": [] - responses: - "200": - description: Objeto `Organization` modificado - content: - application/json: - schema: - $ref: "#/components/schemas/Organization" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /organizations/{organization_id}: - get: - operationId: getOrganization - tags: - - organization - summary: Obtener organización por ID - description: Regresa el objeto 'Organization' relacionado al `id` especificado. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ - -H "Authorization: Bearer sk_user_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_user_API_KEY'); - const organization = await facturapi.organizations.retrieve( - '5a2a307be93a2f00129ea035' - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_user_API_KEY"); - var organization = await facturapi.Organization.RetrieveAsync( - "5a2a307be93a2f00129ea035" - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var organization = facturapi.organizations().retrieve( - "org_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_user_API_KEY"); - $organization = $facturapi->Organizations->retrieve("5a2a307be93a2f00129ea035"); - parameters: - - in: path - name: organization_id - schema: - type: string - required: true - description: ID de la organización - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - - "SecretUserKey": [] - responses: - "200": - description: Objeto `Organization` - content: - application/json: - schema: - $ref: "#/components/schemas/Organization" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - delete: - operationId: deleteOrganization - tags: - - organization - summary: Eliminar organización - description: | - 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. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/organizations/5a2a307be93a2f00129ea035 \ - -X DELETE \ - -H "Authorization: Bearer sk_user_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_user_API_KEY'); - const organization = await facturapi.organizations.del( - '5a2a307be93a2f00129ea035' - ); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_user_API_KEY"); - var organization = await facturapi.Organization.DeleteAsync( - "5a2a307be93a2f00129ea035" - ); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var organization = facturapi.organizations().delete( - "org_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_user_API_KEY"); - $organization = $facturapi->Organizations->delete( - "5a2a307be93a2f00129ea035" + $organization = $facturapi->Organizations->updateDomain( + "5a2a307be93a2f00129ea035", + [ "domain" => "empresa-demo" ] ); parameters: - in: path @@ -9193,12 +9322,15 @@ paths: schema: type: string required: true - description: ID del objeto a eliminar + description: ID de la organización + requestBody: + $ref: "#/components/requestBodies/OrganizationEditDomain" security: + - "SecretLiveKey": [] - "SecretUserKey": [] responses: "200": - description: Objeto `Organization` eliminado correctamente + description: Objeto `Organization` modificado content: application/json: schema: @@ -9207,6 +9339,8 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": @@ -9422,6 +9556,10 @@ paths: type: array items: type: object + required: + - id + - first_12 + - created_at properties: first_12: type: string @@ -9634,7 +9772,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const seriesList = await facturapi.organizations.getSeries( + const seriesList = await facturapi.organizations.listSeriesGroup( '5a2a307be93a2f00129ea035' ); - lang: csharp @@ -9693,7 +9831,7 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - + post: operationId: createSeriesGroup tags: @@ -9721,7 +9859,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const newSeries = await facturapi.organizations.createSeries( + const newSeries = await facturapi.organizations.createSeriesGroup( '5a2a307be93a2f00129ea035', { series: 'New', @@ -9920,13 +10058,13 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const updatedSeries = await facturapi.organizations.updateSeries( + const updatedSeries = await facturapi.organizations.updateSeriesGroup( '5a2a307be93a2f00129ea035', 'New', - [ - "next_folio" => 1, - "next_folio_test" => 1 - ] + { + next_folio: 1, + next_folio_test: 1 + } ); - lang: csharp label: C# @@ -10016,7 +10154,7 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_user_API_KEY'); - const deletedSeries = await facturapi.organizations.deleteSeries( + const deletedSeries = await facturapi.organizations.deleteSeriesGroup( '5a2a307be93a2f00129ea035', 'New' ); @@ -10152,7 +10290,7 @@ paths: summary: Invitar usuario a organización description: | 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). x-codeSamples: @@ -11284,254 +11422,18 @@ paths: import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); const customer = await facturapi.webhooks.create({ - "enabled_events": ["receipt.self_invoice_complete"], - "url": "http://my-website.com/my/webhook" - }); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.CreateAsync(new Dictionary - { - ["enabled_events"] = new Dictionary["receipt.self_invoice_complete"], - ["url"] = "http://my-website.com/my/webhook" - }); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var webhook = facturapi.webhooks().create( - Map.of( - "url", "https://example.com/webhooks", - "triggers", List.of("invoice.created") - )); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->create([ - "enabled_events" => ["receipt.self_invoice_complete"], - "url" => "http://my-website.com/my/webhook" - ]); - requestBody: - $ref: "#/components/requestBodies/WebhookCreate" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "201": - description: Nuevo objeto `Webhook` creado - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "200": - description: Un objeto `Webhook` con la misma información ya existía - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - get: - operationId: listWebhooks - tags: - - webhooks - summary: Listar webhooks - description: Retorna una lista de webhooks creados previamente para la organización. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -G \ - -d 'page=1' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const searchResult = await facturapi.webhooks.list({ - limit: 0, - page: 1 - }); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var searchResult = await facturapi.Webhook.ListAsync(new Dictionary - { - ["page"] = 1 - ["limit"] = 0, - }); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var searchResult = facturapi.webhooks().list( - Map.of( - "page", 0, - "limit", 10 - ) - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $searchResult = $facturapi->Webhooks->all([ - "page" => 1 - ]); - parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Resultado de la búsqueda - content: - application/json: - schema: - $ref: "#/components/schemas/WebhookSearchResult" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - - /webhooks/{webhook_id}: - get: - operationId: getWebhook - tags: - - webhooks - summary: Obtener webhook por ID - description: Regresa el objeto "Webhook" relacionado al `id` especificado. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.retrieve('590ce6c56d04f840aa8438af'); - - lang: csharp - label: C# - source: | - var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.RetrieveAsync("590ce6c56d04f840aa8438af"); - - lang: Java - label: Java - source: | - import io.facturapi.Facturapi; - import java.util.List; - import java.util.Map; - - Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - - var webhook = facturapi.webhooks().retrieve( - "whk_123" - ); - - lang: PHP - source: | - $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->retrieve( "5a3ee743f508333611ad6b3c" ); - parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID del objeto a obtener - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: Objeto `Webhook` - content: - application/json: - schema: - $ref: "#/components/schemas/Webhook" - "400": - $ref: "#/components/responses/BadRequest" - "401": - $ref: "#/components/responses/Unauthenticated" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - put: - operationId: editWebhook - tags: - - webhooks - summary: Editar webhook - description: Actualiza la información de un Webhook existente con los parámetros que envíes en la petición. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -X PUT \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "status": "disabled", - "enabled_events": ["receipt.self_invoice_complete"] - }' - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi' - const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.update( - '590ce6c56d04f840aa8438af', - { - "status": "disabled", - "enabled_events": ["receipt.self_invoice_complete"] - } - ); + "enabled_events": ["receipt.self_invoice_complete"], + "url": "http://my-website.com/my/webhook" + }); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.UpdateAsync( - "590ce6c56d04f840aa8438af", - new Dictionary - { - ["status"] = "disabled", - ["address"] = new Dictionary["receipt.self_invoice_complete"] - } - ); + var customer = await facturapi.Webhook.CreateAsync(new Dictionary + { + ["enabled_events"] = new string[] { "receipt.self_invoice_complete" }, + ["url"] = "http://my-website.com/my/webhook" + }); - lang: Java label: Java source: | @@ -11541,33 +11443,26 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var webhook = facturapi.webhooks().update("whk_123", Map.of( + var webhook = facturapi.webhooks().create( + Map.of( "url", "https://example.com/webhooks", - "triggers", List.of("invoice.created") + "enabled_events", List.of("receipt.self_invoice_complete") )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->update("590ce6c56d04f840aa8438af", [ - "status" => "disabled", - "address" => ["receipt.self_invoice_complete"] - ] + $customer = $facturapi->Webhooks->create([ + "enabled_events" => ["receipt.self_invoice_complete"], + "url" => "http://my-website.com/my/webhook" ]); - parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID del objeto a editar requestBody: - $ref: "#/components/requestBodies/WebhookEdit" + $ref: "#/components/requestBodies/WebhookCreate" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: - "200": - description: Objeto `Webhook` editado correctamente + "201": + description: Nuevo objeto `Webhook` creado content: application/json: schema: @@ -11576,34 +11471,44 @@ paths: $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - delete: - operationId: deleteWebhook + get: + operationId: listWebhooks tags: - webhooks - summary: Eliminar Webhook - description: Elimina el webhook pertenciente a la organización. + summary: Listar webhooks + description: Retorna una lista de webhooks creados previamente para la organización. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ - -X DELETE \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -G \ + -d 'page=1' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const removedCustomer = await facturapi.webhooks.del('590ce6c56d04f840aa8438af'); + const searchResult = await facturapi.webhooks.list({ + limit: 0, + page: 1 + }); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.DeleteAsync("590ce6c56d04f840aa8438af"); + var searchResult = await facturapi.Webhook.ListAsync(new Dictionary + { + ["page"] = 1 + ["limit"] = 0, + }); - lang: Java label: Java source: | @@ -11613,80 +11518,69 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var webhook = facturapi.webhooks().delete( - "whk_123" + var searchResult = facturapi.webhooks().list( + Map.of( + "page", 0, + "limit", 10 + ) ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $facturapi->Webhooks->delete( "5a3fefd9f508333611ad6b43" ); + $searchResult = $facturapi->Webhooks->all([ + "page" => 1 + ]); parameters: - - in: path - name: webhook_id - schema: - type: string - required: true - description: ID del objeto a eliminar + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Objeto `Webhook` eliminado correctamente + description: Resultado de la búsqueda content: application/json: schema: - $ref: "#/components/schemas/Webhook" + $ref: "#/components/schemas/WebhookSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" + "404": + $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /webhooks/validate-signature: - post: - operationId: validateWebhookSignature + + /webhooks/{webhook_id}: + get: + operationId: getWebhook tags: - webhooks - summary: Validar evento de webhook - description: | - 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. + summary: Obtener webhook por ID + description: Regresa el objeto "Webhook" relacionado al `id` especificado. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/webhooks/valdate-signature \ - -H "Authorization: Bearer sk_test_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "secret": "wh_sec...", - "payload": "Object Response", - "signature": "Signature_FROM_HEADER" - }' + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const customer = await facturapi.webhooks.validateSignature({ - secret: "wh_sec...", - payload: "Object Response", - signature: "Signature_FROM_HEADER" - }); + const customer = await facturapi.webhooks.retrieve('590ce6c56d04f840aa8438af'); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - var customer = await facturapi.Webhook.ValidateSignatureAsync(new Dictionary - { - ["secret"] = "wh_sec...", - ["payload"] = new Dictionary["Object Response"], - ["signature"] = "Signature_FROM_HEADER" - }); + var customer = await facturapi.Webhook.RetrieveAsync("590ce6c56d04f840aa8438af"); - lang: Java label: Java source: | @@ -11696,137 +11590,80 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var event = facturapi.webhooks().validateSignature( - "webhook_secret", - "signature_hex", - "{\"id\":\"evt_123\"}" - ); + var webhook = facturapi.webhooks().retrieve( + "whk_123" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - $customer = $facturapi->Webhooks->validateSignature([ - "secret" => "wh_sec...", - "payload" => "Object Response", - "signature" => "Signature_FROM_HEADER" - ]); - requestBody: - content: - application/json: - schema: - type: object - properties: - secret: - type: string - description: Llave secreta del webhook. Se obtiene al crear un webhook o desde el dashboard de Facturapi. - payload: - type: object - description: Objeto ApiEvent recibido mediante el webhook - signature: - type: string - description: Firma del webhook recibida en el header `Facturapi-Signature` + $customer = $facturapi->Webhooks->retrieve( "5a3ee743f508333611ad6b3c" ); + parameters: + - in: path + name: webhook_id + schema: + type: string + required: true + description: ID del objeto a obtener security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Objeto del evento validado + description: Objeto `Webhook` content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - example: "invoice.status_updated" - enum: - - invoice.status_updated - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - - /check: - get: - tags: - - tools - summary: Health check (Pulso) - description: Indica el estatus de disponibilidad de la API. - security: - - "SecretLiveKey": [] - - "SecretTestKey": [] - responses: - "200": - description: La API está operando con normalidad. - content: - application/json: - schema: - type: object - properties: - ok: - type: boolean - example: true - "401": - description: Error de autenticación. Asegúrate de estar usando tu llave secreta. - "502": - description: Servicio temporalmente no disponible. - - /tools/tax_id_validation: - get: + put: + operationId: editWebhook tags: - - tools - summary: Validar RFC - description: | - 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. + - webhooks + summary: Editar webhook + description: Actualiza la información de un Webhook existente con los parámetros que envíes en la petición. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/tools/tax_id_validation?tax_id=BBA830831LJ2 \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -X PUT \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "status": "disabled", + "enabled_events": ["receipt.self_invoice_complete"] + }' - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - - const validation = await facturapi.tools.validateTaxId('BBA830831LJ2'); + const customer = await facturapi.webhooks.update( + '590ce6c56d04f840aa8438af', + { + "status": "disabled", + "enabled_events": ["receipt.self_invoice_complete"] + } + ); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var customer = await facturapi.Tool.ValidateTaxIdAsync("BBA830831LJ2"); + var customer = await facturapi.Webhook.UpdateAsync( + "590ce6c56d04f840aa8438af", + new Dictionary + { + ["status"] = "disabled", + ["enabled_events"] = new string[] { "receipt.self_invoice_complete" } + } + ); - lang: Java label: Java source: | @@ -11836,32 +11673,36 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var validation = facturapi.tools().validateTaxId( - "XAXX010101000" - ); + var webhook = facturapi.webhooks().update("whk_123", Map.of( + "status", "disabled", + "enabled_events", List.of("receipt.self_invoice_complete") + )); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $customer = $facturapi->Tools->validateTaxId("BBA830831LJ2"); + $customer = $facturapi->Webhooks->update("590ce6c56d04f840aa8438af", [ + "status" => "disabled", + "enabled_events" => ["receipt.self_invoice_complete"] + ]); parameters: - - in: query - name: tax_id - required: true + - in: path + name: webhook_id schema: type: string - description: RFC a validar - example: BBA830831LJ2 + required: true + description: ID del objeto a editar + requestBody: + $ref: "#/components/requestBodies/WebhookEdit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Resultado de la validación + description: Objeto `Webhook` editado correctamente content: application/json: schema: - $ref: "#/components/schemas/TaxIdValidationResult" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": @@ -11870,38 +11711,30 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /catalogs/products: - get: + delete: + operationId: deleteWebhook tags: - - sat_keys - summary: Clave Producto/Servicio - description: Busca en el catálogo Productos/Servicios del SAT, el cual contiene la clave a incluir en la factura. + - webhooks + summary: Eliminar Webhook + description: Elimina el webhook perteneciente a la organización. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/catalogs/products?q=ukelele \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/590ce6c56d04f840aa8438af \ + -X DELETE \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - - const searchResult = await facturapi.catalogs.searchProducts({ - q: 'ukelele' - }); + const removedCustomer = await facturapi.webhooks.del('590ce6c56d04f840aa8438af'); - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Catalog.SearchProducts( - new Dictionary - { - ["q"] = "ukelele" - } - ); + var customer = await facturapi.Webhook.DeleteAsync("590ce6c56d04f840aa8438af"); - lang: Java label: Java source: | @@ -11911,84 +11744,90 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var result = facturapi.catalogs().searchProducts( - Map.of( - "q", "0101", - "page", 0, - "limit", 10 - ) + var webhook = facturapi.webhooks().delete( + "whk_123" ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $result = $facturapi->Catalogs->searchProducts([ - "q" => "ukelele" - ]); + $facturapi->Webhooks->delete( "5a3fefd9f508333611ad6b43" ); parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q + - in: path + name: webhook_id schema: type: string - description: Consulta. Texto a buscar en la descripción de la clasificación. - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + required: true + description: ID del objeto a eliminar security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Resultado de la búsqueda + description: Objeto `Webhook` eliminado correctamente content: application/json: schema: - $ref: "#/components/schemas/ProductCatalogSearchResult" + $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /catalogs/units: - get: + /webhooks/validate-signature: + post: + operationId: validateWebhookSignature tags: - - sat_keys - summary: Unidades de medida - description: Busca en el catálogo de Unidades de Medida del SAT. + - webhooks + summary: Validar evento de webhook + description: | + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/catalogs/units?q=pulgada \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/webhooks/validate-signature \ + -H "Authorization: Bearer sk_test_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "secret": "wh_sec...", + "payload": "Object Response", + "signature": "Signature_FROM_HEADER" + }' - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi' + import Facturapi from 'facturapi'; const facturapi = new Facturapi('sk_test_API_KEY'); - const searchResult = await facturapi.catalogs.searchUnits({ - q: 'pulgada' - }); + // Pasa el body original sin parsearlo y la firma del encabezado Facturapi-Signature. + /** + * @param {string | Uint8Array | ArrayBuffer} rawBody + * @param {string} signature + * @param {string} secret + */ + export async function verifyWebhook(rawBody, signature, secret) { + const event = await facturapi.webhooks.validateSignature({ + secret, + signature, + payload: rawBody + }); + return event; + } - lang: csharp label: C# source: | var facturapi = new FacturapiClient("sk_test_API_KEY"); - - var searchResult = await facturapi.Catalog.SearchUnits( - new Dictionary - { - ["q"] = "pulgada" - } - ); + var customer = await facturapi.Webhook.ValidateSignatureAsync(new Dictionary + { + ["secret"] = "wh_sec...", + ["payload"] = new Dictionary["Object Response"], + ["signature"] = "Signature_FROM_HEADER" + }); - lang: Java label: Java source: | @@ -11998,42 +11837,56 @@ paths: Facturapi facturapi = new Facturapi("sk_test_API_KEY"); - var result = facturapi.catalogs().searchUnits( - Map.of( - "q", "H87", - "page", 0, - "limit", 10 - ) - ); + var event = facturapi.webhooks().validateSignature( + "webhook_secret", + "signature_hex", + "{\"id\":\"evt_123\"}" + ); - lang: PHP source: | $facturapi = new Facturapi("sk_test_API_KEY"); - - $result = $facturapi->Catalogs->searchUnits([ - "q" => "pulgada" + $customer = $facturapi->Webhooks->validateSignature([ + "secret" => "wh_sec...", + "payload" => "Object Response", + "signature" => "Signature_FROM_HEADER" ]); - parameters: - - $ref: "#/components/parameters/SearchPagination" - - $ref: "#/components/parameters/SearchAfter" - - $ref: "#/components/parameters/SearchBefore" - - - in: query - name: q - schema: - type: string - description: Consulta. Texto a buscar en la descripción de la unidad de medida. - - $ref: "#/components/parameters/SearchPage" - - $ref: "#/components/parameters/SearchLimit" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + secret: + type: string + description: Llave secreta del webhook. Se obtiene al crear un webhook o desde el dashboard de Facturapi. + payload: + oneOf: + - type: string + - type: object + additionalProperties: true + description: "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." + signature: + type: string + description: Firma del webhook recibida en el header `Facturapi-Signature` + required: + - secret + - payload + - signature security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Resultado de la búsqueda + description: Payload original con firma válida content: application/json: schema: - $ref: "#/components/schemas/UnitCatalogSearchResult" + oneOf: + - type: string + - type: object + additionalProperties: true + description: "Devuelve el payload original cuando la firma es válida: un string si enviaste texto JSON, o un objeto si enviaste un objeto. No convierte el string a objeto." "400": $ref: "#/components/responses/BadRequest" "401": @@ -12044,179 +11897,193 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/download-url/{format}: + + /check: get: - operationId: getInvoiceDownloadUrl + operationId: "checkApiHealth" tags: - - invoice - summary: Obtener enlace de descarga - description: | - Devuelve 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. - x-codeSamples: - - lang: Bash - label: cURL - source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" - - lang: JavaScript - label: Node.js - source: | - import Facturapi from 'facturapi'; - - const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.invoices.downloadPdfUrl( - '58e93bd8e86eb318b019743d' - ); - - console.log(download.url, download.expires_at); - parameters: - - in: path - name: invoice_id - schema: - type: string - required: true - description: ID del objeto a descargar - - in: path - name: format - schema: - type: string - enum: - - pdf - - xml - - zip - required: true - description: Formato del archivo de descarga + - tools + summary: Health check (Pulso) + description: "Comprueba que la API está disponible. Este endpoint requiere una llave secreta de API." security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Enlace temporal de descarga del comprobante CFDI en el formato solicitado + description: La API está operando con normalidad. content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" - "400": - $ref: "#/components/responses/BadRequest" + type: object + properties: + ok: + type: boolean + example: true "401": - $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" - "409": - $ref: "#/components/responses/Conflict" - "429": - $ref: "#/components/responses/RateLimited" - "500": - $ref: "#/components/responses/UnexpectedError" - /invoices/{invoice_id}/cancellation_receipt/download-url/{format}: + description: Error de autenticación. Asegúrate de estar usando tu llave secreta. + "502": + description: Servicio temporalmente no disponible. + + /tools/tax_id_validation: get: - operationId: getCancellationReceiptDownloadUrl + operationId: validateTaxId tags: - - invoice - summary: Obtener enlace del acuse de cancelación + - tools + summary: Validar RFC description: | - Devuelve 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. + 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). - El enlace da acceso a ese archivo mientras siga vigente: trátalo como una credencial y no lo almacenes. + 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. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/invoices/58e93bd8e86eb318b019743d/cancellation_receipt/download-url/pdf \ + curl https://www.facturapi.io/v2/tools/tax_id_validation?tax_id=BBA830831LJ2 \ -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; + import Facturapi from 'facturapi' + const facturapi = new Facturapi('sk_test_API_KEY'); + + const validation = await facturapi.tools.validateTaxId('BBA830831LJ2'); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); - const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.invoices.downloadCancellationReceiptPdfUrl( - '58e93bd8e86eb318b019743d' - ); + var customer = await facturapi.Tool.ValidateTaxIdAsync("BBA830831LJ2"); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - console.log(download.url, download.expires_at); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var validation = facturapi.tools().validateTaxId( + "XAXX010101000" + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $customer = $facturapi->Tools->validateTaxId("BBA830831LJ2"); parameters: - - in: path - name: invoice_id - schema: - type: string + - in: query + name: tax_id required: true - description: ID del objeto a descargar - - in: path - name: format schema: type: string - enum: - - xml - - pdf - required: true - description: Formato del acuse de cancelación + description: RFC a validar + example: BBA830831LJ2 security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Enlace temporal de descarga del acuse de cancelación en el formato solicitado + description: Resultado de la validación content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/TaxIdValidationResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" - "404": - $ref: "#/components/responses/NotFound" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /receipts/{receipt_id}/download-url/pdf: + /catalogs/products: get: - operationId: getReceiptDownloadUrl + operationId: searchProducts tags: - - receipt - summary: Obtener enlace de descarga - description: | - Devuelve 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. + - sat_keys + summary: Clave Producto/Servicio + description: Busca en el catálogo Productos/Servicios del SAT, el cual contiene la clave a incluir en la factura. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/receipts/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/catalogs/products?q=ukelele \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.receipts.downloadPdfUrl( - '58e93bd8e86eb318b019743d' + + const searchResult = await facturapi.catalogs.searchProducts({ + q: 'ukelele' + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Catalog.SearchProducts( + new Dictionary + { + ["q"] = "ukelele" + } ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - console.log(download.url, download.expires_at); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var result = facturapi.catalogs().searchProducts( + Map.of( + "q", "0101", + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $result = $facturapi->Catalogs->searchProducts([ + "q" => "ukelele" + ]); parameters: - - in: path - name: receipt_id + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q schema: type: string - required: true - description: ID del objeto a descargar + description: Consulta. Texto a buscar en la descripción de la clasificación. + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Enlace temporal de descarga del recibo digital en formato PDF + description: Resultado de la búsqueda content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/ProductCatalogSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": @@ -12227,74 +12094,96 @@ paths: $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" - /retentions/{retention_id}/download-url/{format}: + /catalogs/units: get: - operationId: getRetentionDownloadUrl + operationId: searchUnits tags: - - retention - summary: Obtener enlace de descarga - description: | - Devuelve 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. + - sat_keys + summary: Unidades de medida + description: Busca en el catálogo de Unidades de Medida del SAT. x-codeSamples: - lang: Bash label: cURL source: | - curl https://www.facturapi.io/v2/retentions/58e93bd8e86eb318b019743d/download-url/pdf \ - -H "Authorization: Bearer sk_test_API_KEY" + curl https://www.facturapi.io/v2/catalogs/units?q=pulgada \ + -H "Authorization: Bearer sk_test_API_KEY" - lang: JavaScript label: Node.js source: | - import Facturapi from 'facturapi'; - + import Facturapi from 'facturapi' const facturapi = new Facturapi('sk_test_API_KEY'); - const download = await facturapi.retentions.downloadPdfUrl( - '58e93bd8e86eb318b019743d' + + const searchResult = await facturapi.catalogs.searchUnits({ + q: 'pulgada' + }); + - lang: csharp + label: C# + source: | + var facturapi = new FacturapiClient("sk_test_API_KEY"); + + var searchResult = await facturapi.Catalog.SearchUnits( + new Dictionary + { + ["q"] = "pulgada" + } ); + - lang: Java + label: Java + source: | + import io.facturapi.Facturapi; + import java.util.List; + import java.util.Map; - console.log(download.url, download.expires_at); + Facturapi facturapi = new Facturapi("sk_test_API_KEY"); + + var result = facturapi.catalogs().searchUnits( + Map.of( + "q", "H87", + "page", 0, + "limit", 10 + ) + ); + - lang: PHP + source: | + $facturapi = new Facturapi("sk_test_API_KEY"); + + $result = $facturapi->Catalogs->searchUnits([ + "q" => "pulgada" + ]); parameters: - - in: path - name: retention_id - schema: - type: string - required: true - description: ID del objeto a descargar - - in: path - name: format + - $ref: "#/components/parameters/SearchPagination" + - $ref: "#/components/parameters/SearchAfter" + - $ref: "#/components/parameters/SearchBefore" + + - in: query + name: q schema: type: string - enum: - - pdf - - xml - - zip - required: true - description: Formato del archivo de descarga + description: Consulta. Texto a buscar en la descripción de la unidad de medida. + - $ref: "#/components/parameters/SearchPage" + - $ref: "#/components/parameters/SearchLimit" security: - "SecretLiveKey": [] - "SecretTestKey": [] responses: "200": - description: Enlace temporal de descarga de la retención en el formato solicitado + description: Resultado de la búsqueda content: application/json: schema: - $ref: "#/components/schemas/SignedDownloadUrl" + $ref: "#/components/schemas/UnitCatalogSearchResult" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthenticated" "404": $ref: "#/components/responses/NotFound" - "409": - $ref: "#/components/responses/Conflict" "429": $ref: "#/components/responses/RateLimited" "500": $ref: "#/components/responses/UnexpectedError" -x-webhooks: - "Factura global creada": +webhooks: + invoice.global_invoice_created: post: summary: Factura global creada description: | @@ -12306,27 +12195,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - example: "invoice.global_invoice_created" - enum: - - invoice.global_invoice_created - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - "Estatus de factura actualizado": + $ref: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + operationId: onInvoiceGlobalInvoiceCreated + responses: + '200': + description: OK + invoice.status_updated: post: summary: Estatus de factura actualizado description: | @@ -12340,37 +12214,13 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - example: "invoice.status_updated" - enum: - - invoice.status_updated - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - related_resource_messages: - type: array - description: Mensajes relacionados con el recurso asociado al evento. - items: - $ref: "#/components/schemas/RelatedResourceMessage" + $ref: '#/components/schemas/InvoiceStatusUpdatedEvent' examples: with_related_messages: summary: Con mensajes relacionados value: id: evt_xxx - created_at: "2026-07-01T12:00:00.000Z" + created_at: '2026-07-01T12:00:00.000Z' livemode: true organization: org_xxx type: invoice.status_updated @@ -12384,12 +12234,12 @@ x-webhooks: source: stamping_async_task severity: error message: El RFC del receptor no es válido - created_at: "2026-01-01T00:00:00.000Z" + created_at: '2026-01-01T00:00:00.000Z' without_related_messages: summary: Sin mensajes relacionados value: id: evt_xxx - created_at: "2026-07-01T12:00:00.000Z" + created_at: '2026-07-01T12:00:00.000Z' livemode: true organization: org_xxx type: invoice.status_updated @@ -12398,7 +12248,11 @@ x-webhooks: object: id: invoice_xxx related_resource_messages: [] - "Creación de factura desde dashboard": + operationId: onInvoiceStatusUpdated + responses: + '200': + description: OK + invoice.created_from_dashboard: post: summary: Creación de factura desde dashboard description: | @@ -12410,27 +12264,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - example: "invoice.created_from_dashboard" - enum: - - invoice.created_from_dashboard - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - "Estatus de cancelación actualizado": + $ref: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + operationId: onInvoiceCreatedFromDashboard + responses: + '200': + description: OK + invoice.cancellation_status_updated: post: tags: - events @@ -12440,28 +12279,14 @@ x-webhooks: requestBody: required: true content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - enum: - - invoice.cancellation_status_updated - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - invoice - object: - $ref: "#/components/schemas/Invoice" - "Autofactura completada": + application/json: + schema: + $ref: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + operationId: onInvoiceCancellationStatusUpdated + responses: + '200': + description: OK + receipt.self_invoice_complete: post: tags: - events @@ -12473,27 +12298,12 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - example: "receipt.self_invoice_complete" - enum: - - receipt.self_invoice_complete - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - receipt - object: - $ref: "#/components/schemas/Receipt" - "Estatus de recibo actualizado": + $ref: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + operationId: onReceiptSelfInvoiceComplete + responses: + '200': + description: OK + receipt.status_updated: post: tags: - events @@ -12505,25 +12315,26 @@ x-webhooks: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/EventBase" - - type: object - properties: - type: - type: string - description: Tipo de evento - enum: - - receipt.status_updated - data: - type: object - properties: - type: - type: string - description: Tipo de objeto asociado al evento - enum: - - receipt - object: - $ref: "#/components/schemas/Receipt" + $ref: '#/components/schemas/ReceiptStatusUpdatedEvent' + operationId: onReceiptStatusUpdated + responses: + '200': + description: OK + customer.edit_link_completed: + post: + summary: Edición de cliente completada + tags: + - events + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEditLinkCompletedEvent' + responses: + '200': + description: OK + operationId: onCustomerEditLinkCompleted components: responses: BadRequest: @@ -12655,7 +12466,7 @@ components: application/json: schema: allOf: - - $ref: "#/components/schemas/ProductProperties" + - $ref: "#/components/schemas/ProductEditableProperties" InvoiceCreate: required: true content: @@ -12678,7 +12489,7 @@ components: content: application/json: schema: - oneOf: + anyOf: - $ref: "#/components/schemas/InvoiceIngresoEditInput" - $ref: "#/components/schemas/InvoiceEgresoEditInput" - $ref: "#/components/schemas/InvoicePagoEditInput" @@ -12875,7 +12686,7 @@ components: schema: type: integer minimum: 1 - default: 50 + default: 100 maximum: 100 description: Número del 1 al 100 que representa la cantidad máxima de resultados a regresar con motivos de paginación. @@ -12906,9 +12717,219 @@ components: Devuelve los resultados anteriores al cursor indicado. Solo con `pagination=cursor`; mutuamente excluyente con `after`. schemas: + DateOrDateTime: + description: Fecha en formato YYYY-MM-DD o fecha y hora en formato ISO8601. + anyOf: + - type: string + format: date + - type: string + format: date-time + InvoiceGlobalInvoiceCreatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + example: invoice.global_invoice_created + enum: + - invoice.global_invoice_created + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + example: invoice.status_updated + enum: + - invoice.status_updated + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceCreatedFromDashboardEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + example: invoice.created_from_dashboard + enum: + - invoice.created_from_dashboard + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + InvoiceCancellationStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + enum: + - invoice.cancellation_status_updated + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - invoice + object: + $ref: '#/components/schemas/Invoice' + required: + - type + - object + required: + - type + - data + ReceiptSelfInvoiceCompleteEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + example: receipt.self_invoice_complete + enum: + - receipt.self_invoice_complete + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - receipt + object: + $ref: '#/components/schemas/Receipt' + required: + - type + - object + required: + - type + - data + ReceiptStatusUpdatedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + description: Tipo de evento + enum: + - receipt.status_updated + data: + type: object + properties: + type: + type: string + description: Tipo de objeto asociado al evento + enum: + - receipt + object: + $ref: '#/components/schemas/Receipt' + required: + - type + - object + required: + - type + - data + CustomerEditLinkCompletedEvent: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + type: + type: string + enum: + - customer.edit_link_completed + data: + type: object + properties: + type: + type: string + enum: + - customer + object: + $ref: '#/components/schemas/Customer' + required: + - type + - object + required: + - type + - data + ApiEvent: + oneOf: + - $ref: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + - $ref: '#/components/schemas/InvoiceStatusUpdatedEvent' + - $ref: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + - $ref: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + - $ref: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + - $ref: '#/components/schemas/ReceiptStatusUpdatedEvent' + - $ref: '#/components/schemas/CustomerEditLinkCompletedEvent' + discriminator: + propertyName: type + mapping: + invoice.global_invoice_created: '#/components/schemas/InvoiceGlobalInvoiceCreatedEvent' + invoice.status_updated: '#/components/schemas/InvoiceStatusUpdatedEvent' + invoice.created_from_dashboard: '#/components/schemas/InvoiceCreatedFromDashboardEvent' + invoice.cancellation_status_updated: '#/components/schemas/InvoiceCancellationStatusUpdatedEvent' + receipt.self_invoice_complete: '#/components/schemas/ReceiptSelfInvoiceCompleteEvent' + receipt.status_updated: '#/components/schemas/ReceiptStatusUpdatedEvent' + customer.edit_link_completed: '#/components/schemas/CustomerEditLinkCompletedEvent' SignedDownloadUrl: type: object - description: Enlace temporal de descarga de un archivo. + description: Objeto con un enlace temporal de descarga y los metadatos del archivo. required: - url - expires_at @@ -12917,6 +12938,7 @@ components: properties: url: type: string + format: uri description: Enlace de descarga. Da acceso al archivo mientras siga vigente. expires_at: type: string @@ -12946,14 +12968,6 @@ components: description: type: string description: Descripción de la entrada del catálogo - ErrorMessage: - type: object - required: - - message - properties: - message: - type: string - description: Descripción del error y posible sugerencia. RelatedResourceMessage: type: object properties: @@ -12997,7 +13011,7 @@ components: type: string format: date-time description: Fecha y hora de creación del evento - example: 2022-03-30T00:00:00Z + example: '2022-03-30T00:00:00Z' livemode: type: boolean description: Indica si el evento se generó en modo test (false) o en modo producción (true). @@ -13006,6 +13020,16 @@ components: type: string description: ID de la organización a la que pertenece el evento example: 61f81a7fbd4661b11b9b3f27 + related_resource_messages: + type: array + description: Mensajes relacionados con el recurso asociado al evento. + items: + $ref: '#/components/schemas/RelatedResourceMessage' + required: + - id + - created_at + - livemode + - organization DateRange: type: object properties: @@ -13128,12 +13152,14 @@ components: type: integer example: 1 title: Página - description: Número de página de resultados + description: "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." + minimum: 0 total_pages: type: integer example: 1 title: Páginas totales - description: Número total de páginas de resultados + description: "Total de páginas. Se omite en todas las respuestas de paginación por cursor, incluida la primera página." + minimum: 0 total_results: type: integer example: 1 @@ -13141,12 +13167,16 @@ components: description: | 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. previous_cursor: - type: [string, "null"] + type: + - string + - 'null' example: null title: Cursor anterior description: Cursor para obtener la página anterior de resultados. Es `null` en la primera página. Solo disponible con `pagination=cursor`. next_cursor: - type: [string, "null"] + type: + - string + - 'null' example: null title: Cursor siguiente description: Cursor para obtener la página siguiente de resultados. Es `null` cuando no hay más resultados. Solo disponible con `pagination=cursor`. @@ -13267,14 +13297,14 @@ components: example: 08/06/2021 format: "DD/MM/YYYY" description: Fecha de sentencia favorable - + ProductCatalogResult: type: object properties: key: type: string description: Clave del catálogo - example: 60131324 + example: "60131324" description: type: string description: Descripción @@ -13307,6 +13337,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -13316,13 +13348,15 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array items: $ref: "#/components/schemas/UnitCatalogResult" - + LocalTax: type: object required: @@ -13331,12 +13365,11 @@ components: properties: rate: type: number - example: 0.10 + example: 0.1 description: Tasa del impuesto en fracción decimal. base: type: number - default: 100% del subtotal - description: Base del impuesto + description: "Base del impuesto. Si se omite, se utiliza el subtotal completo del concepto." type: type: string description: Nombre del impuesto. Texto libre. @@ -13344,6 +13377,12 @@ components: type: boolean default: false description: Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + factor: + type: string + enum: + - Tasa + - Cuota + - Exento BaseTax: title: Tax type: object @@ -13362,8 +13401,7 @@ components: description: Tasa del impuesto en fracción decimal. base: type: number - default: 100% del subtotal - description: Base del impuesto. + description: "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." type: type: string default: IVA @@ -13372,6 +13410,8 @@ components: - IVA - ISR - IEPS + ieps_mode: + $ref: "#/components/schemas/IepsMode" factor: type: string default: Tasa @@ -13384,33 +13424,40 @@ components: type: boolean default: false description: Indica si se trata de un impuesto retenido (`true`), o un impuesto trasladado (`false`) + IepsMode: + type: string + default: sum_before_taxes + enum: + - sum_before_taxes + - break_down + - unit + - subtract_before_break_down + description: | + 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. + IepsTax: type: object allOf: - $ref: "#/components/schemas/BaseTax" - type: object + required: + - type properties: - ieps_mode: + type: type: string - default: sum_before_taxes - enum: - - sum_before_taxes - - break_down - - unit - - subtract_before_break_down - description: | - 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. - + const: IEPS + ieps_mode: + $ref: "#/components/schemas/IepsMode" Stamp: type: object description: Información sobre el timbre fiscal digital agregado por el PAC. @@ -13420,8 +13467,8 @@ components: description: Sello digital del comprobante fiscal. date: type: string - format: date-time - description: Fecha de timbrado en formato ISO8601 (UTC String). + description: "FechaTimbrado del SAT: fecha y hora local sin offset de zona horaria. Se conserva como texto." + example: "2026-09-17T06:59:16" sat_cert_number: type: string description: Número de serie del certificado del SAT usado para timbrar. @@ -13432,6 +13479,11 @@ components: LineItem: type: object properties: + property_tax_account: + type: array + items: + type: string + description: Cuentas prediales de este concepto. quantity: type: number description: Cantidad de unidades incluidas del mismo concepto. @@ -13444,7 +13496,9 @@ components: $ref: "#/components/schemas/LineItemProduct" description: Objeto con información del producto o servicio facturado. parts: - $ref: "#/components/schemas/Parts" + type: array + items: + $ref: "#/components/schemas/Parts" description: Objeto con información de las partes de la factura. ThirdParty: type: object @@ -13769,6 +13823,9 @@ components: CustomComplementProperties: title: CustomComplement type: object + required: + - type + - data properties: type: type: string @@ -13778,24 +13835,22 @@ components: data: $ref: '#/components/schemas/CustomComplementData' CustomComplementInput: + required: + - type + - data title: CustomComplement allOf: - - type: object - required: - - type - - data - $ref: "#/components/schemas/CustomComplementProperties" NominaComplementDataInput: + required: + - fecha_inicial_pago + - fecha_final_pago + - num_dias_pagados + - receptor + - percepciones title: NominaComplementData description: Objeto con la información del complemento de nómina. allOf: - - type: object - required: - - fecha_inicial_pago - - fecha_final_pago - - num_dias_pagados - - receptor - - percepciones - $ref: "#/components/schemas/NominaComplementDataDirectProperties" - $ref: "#/components/schemas/NominaComplementDataNestedInput" NominaComplementDataProperties: @@ -13817,17 +13872,16 @@ components: - `“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. fecha_pago: - type: string - format: date - default: now - description: Fecha de pago de la nómina al trabajador. + allOf: + - $ref: "#/components/schemas/DateOrDateTime" + description: "Fecha de pago de la nómina al trabajador. Si se omite, se utiliza la fecha y hora actuales." fecha_inicial_pago: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: Fecha inicial del periodo de pago. fecha_final_pago: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: Fecha final del periodo de pago. num_dias_pagados: type: number @@ -13837,7 +13891,7 @@ components: type: object properties: emisor: - $ref: "#/components/schemas/NominaEmisorProperties" + $ref: "#/components/schemas/NominaEmisorInput" receptor: $ref: "#/components/schemas/NominaReceptorInput" percepciones: @@ -13894,12 +13948,11 @@ components: $ref: "#/components/schemas/NominaIncapacidadProperties" NominaIncapacidadInput: + required: + - dias_incapacidad + - tipo_incapacidad title: Incapacidad allOf: - - type: object - required: - - dias_incapacidad - - tipo_incapacidad - $ref: "#/components/schemas/NominaIncapacidadProperties" NominaIncapacidadProperties: type: object @@ -13914,13 +13967,12 @@ components: type: number description: Monto del importe monetario de la incapacidad. NominaOtroPagoInput: + required: + - tipo_otro_pago + - clave + - importe title: OtroPago allOf: - - type: object - required: - - tipo_otro_pago - - clave - - importe - $ref: "#/components/schemas/NominaOtroPagoDirectProperties" - type: object properties: @@ -13952,12 +14004,11 @@ components: Este valor será insertado dentro del nodo `SubsidioAlEmpleo`, y es requerido cuando el valor de `tipo_otro_pago` es `"002"`. NominaCompensacionInput: + required: + - saldo_a_favor + - ano + - remanente_sal_fav allOf: - - type: object - required: - - saldo_a_favor - - ano - - remanente_sal_fav - $ref: "#/components/schemas/NominaCompensacionProperties" NominaCompensacionProperties: type: object @@ -13973,13 +14024,12 @@ components: type: number description: Remanente del saldo a favor del trabajador. NominaDeduccionInput: + required: + - tipo_deduccion + - clave + - importe title: Deduccion allOf: - - type: object - required: - - tipo_deduccion - - clave - - importe - $ref: "#/components/schemas/NominaDeduccionProperties" NominaDeduccionProperties: type: object @@ -14029,15 +14079,14 @@ components: separacion_indemnizacion: $ref: "#/components/schemas/NominaSeparacionProperties" NominaSeparacionInput: + required: + - total_pagado + - num_anos_servicio + - ultimo_sueldo_mens_ord + - ingreso_acumulable + - ingreso_no_acumulable title: Separacion allOf: - - type: object - required: - - total_pagado - - num_anos_servicio - - ultimo_sueldo_mens_ord - - ingreso_acumulable - - ingreso_no_acumulable - $ref: "#/components/schemas/NominaSeparacionProperties" NominaSeparacionProperties: type: object @@ -14060,12 +14109,11 @@ components: type: number description: Monto por ingresos no acumulables. NominaJubilacionInput: + required: + - ingreso_acumulable + - ingreso_no_acumulable title: Jubilacion allOf: - - type: object - required: - - ingreso_acumulable - - ingreso_no_acumulable - $ref: "#/components/schemas/NominaJubilacionProperties" NominaJubilacionProperties: type: object @@ -14092,16 +14140,79 @@ components: - $ref: "#/components/schemas/NominaPercepcionDirectProperties" - $ref: "#/components/schemas/NominaPercepcionNestedProperties" NominaPercepcionInput: + required: + - tipo_percepcion + - clave + - importe_gravado + - importe_exento + description: "La entrada utiliza las claves de percepción del catálogo publicado. La clave 019 requiere horas_extra." title: Percepcion allOf: - - type: object - required: - - tipo_percepcion - - clave - - importe_gravado - - importe_exento - $ref: "#/components/schemas/NominaPercepcionDirectProperties" - $ref: "#/components/schemas/NominaPercepcionNestedInput" + oneOf: + - type: object + properties: + tipo_percepcion: + type: string + const: "019" + horas_extra: + type: array + items: + $ref: "#/components/schemas/NominaHorasExtraInput" + required: + - horas_extra + - type: object + properties: + tipo_percepcion: + type: string + enum: + - "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: type: object properties: @@ -14143,14 +14254,13 @@ components: items: $ref: "#/components/schemas/NominaHorasExtraProperties" NominaHorasExtraInput: + required: + - dias + - tipo_horas + - horas_extra + - importe_pagado title: HorasExtra allOf: - - type: object - required: - - dias - - tipo_horas - - horas_extra - - importe_pagado - $ref: "#/components/schemas/NominaHorasExtraProperties" NominaHorasExtraProperties: type: object @@ -14169,12 +14279,11 @@ components: type: number description: Importe pagado por las horas extra. NominaAccionesInput: + required: + - valor_mercado + - precio_al_otorgarse title: Accion allOf: - - type: object - required: - - valor_mercado - - precio_al_otorgarse - $ref: "#/components/schemas/NominaAccionesProperties" NominaAccionesProperties: type: object @@ -14195,18 +14304,17 @@ components: - $ref: "#/components/schemas/NominaReceptorDirectProperties" - $ref: "#/components/schemas/NominaReceptorNestedProperties" NominaReceptorInput: + required: + - curp + - tipo_contrato + - tipo_regimen + - num_empleado + - periodicidad_pago + - clave_ent_fed type: object title: Receptor description: Información del trabajador. allOf: - - type: object - required: - - curp - - tipo_contrato - - tipo_regimen - - num_empleado - - periodicidad_pago - - clave_ent_fed - $ref: "#/components/schemas/NominaReceptorDirectProperties" - $ref: "#/components/schemas/NominaReceptorNestedInput" NominaReceptorDirectProperties: @@ -14219,8 +14327,8 @@ components: type: string description: Número de seguridad social. fecha_inicio_rel_laboral: - type: string - format: date + allOf: + - $ref: "#/components/schemas/DateOrDateTime" description: Fecha de inicio de la relación laboral entre el empleador y el empleado. antiguedad: oneOf: @@ -14308,6 +14416,38 @@ components: minimum: 0.001 maximum: 100.000 description: Porcentaje de tiempo en que el trabajador prestó sus servicios a la persona o empresa que lo subcontrató. + NominaEntidadSncfInput: + type: object + required: + - origen_recurso + properties: + origen_recurso: + type: string + enum: [IP, IF, IM] + monto_recurso_propio: + type: number + oneOf: + - type: object + properties: + origen_recurso: + type: string + const: IM + monto_recurso_propio: + type: number + required: + - monto_recurso_propio + - type: object + properties: + origen_recurso: + type: string + enum: [IP, IF] + NominaEmisorInput: + allOf: + - $ref: "#/components/schemas/NominaEmisorProperties" + - type: object + properties: + entidad_sncf: + $ref: "#/components/schemas/NominaEntidadSncfInput" NominaEmisorProperties: type: object title: Emisor @@ -14363,6 +14503,10 @@ components: - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/PagoComplementProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + PagoOrCustomComplementInput: type: object title: Complement @@ -14378,30 +14522,99 @@ components: type: type: string enum: - - nomina + - pago - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/PagoComplementInput" + - $ref: "#/components/schemas/CustomComplementInput" + PagoComplementProperties: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: pago - type: object properties: data: - $ref: "#/components/schemas/NominaComplementDataProperties" + $ref: "#/components/schemas/PagoComplementDataProperties" PagoComplementInput: allOf: - - $ref: "#/components/schemas/PagoOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: pago - type: object properties: data: $ref: "#/components/schemas/PagoComplementDataInput" - PagoComplementDataInput: + InvoiceComplementInput: + oneOf: + - $ref: "#/components/schemas/PagoComplementInput" + - $ref: "#/components/schemas/NominaComplementInput" + - $ref: "#/components/schemas/CartaPorteInput" + - $ref: "#/components/schemas/ComercioExteriorInput" + - $ref: "#/components/schemas/LeyendasFiscalesInput" + - $ref: "#/components/schemas/CustomComplementInput" + discriminator: + propertyName: type + mapping: + pago: "#/components/schemas/PagoComplementInput" + nomina: "#/components/schemas/NominaComplementInput" + carta_porte: "#/components/schemas/CartaPorteInput" + comercio_exterior: "#/components/schemas/ComercioExteriorInput" + leyendas_fiscales: "#/components/schemas/LeyendasFiscalesInput" + custom: "#/components/schemas/CustomComplementInput" + InvoiceComplementProperties: + oneOf: + - $ref: '#/components/schemas/PagoComplementProperties' + - $ref: '#/components/schemas/NominaComplementProperties' + - $ref: '#/components/schemas/CartaPorteProperties' + - $ref: '#/components/schemas/ComercioExteriorProperties' + - $ref: '#/components/schemas/LeyendasFiscalesProperties' + - $ref: '#/components/schemas/CustomComplementProperties' + discriminator: + propertyName: type + mapping: + pago: '#/components/schemas/PagoComplementProperties' + nomina: '#/components/schemas/NominaComplementProperties' + carta_porte: '#/components/schemas/CartaPorteProperties' + comercio_exterior: '#/components/schemas/ComercioExteriorProperties' + leyendas_fiscales: '#/components/schemas/LeyendasFiscalesProperties' + custom: '#/components/schemas/CustomComplementProperties' + PagoComplementDataProperties: type: array - title: PagoComplementData - description: 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. items: - $ref: "#/components/schemas/PaymentInput" + $ref: '#/components/schemas/PaymentProperties' + PaymentProperties: + allOf: + - $ref: '#/components/schemas/PaymentInput' + - type: object + required: + - date + properties: + date: + type: string + format: date-time + PagoComplementDataInput: + title: PagoComplementData + description: 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. + oneOf: + - $ref: "#/components/schemas/PaymentInput" + - type: array + minItems: 1 + items: + $ref: "#/components/schemas/PaymentInput" NominaOrCustomComplementProperties: title: Complement type: object @@ -14418,6 +14631,10 @@ components: - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/NominaComplementProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + NominaOrCustomComplementInput: type: object title: Complement @@ -14436,16 +14653,34 @@ components: - nomina - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/NominaComplementInput" + - $ref: "#/components/schemas/CustomComplementInput" + NominaComplementProperties: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: nomina - type: object properties: data: $ref: "#/components/schemas/NominaComplementDataProperties" NominaComplementInput: allOf: - - $ref: "#/components/schemas/NominaOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: nomina - type: object properties: data: @@ -14453,42 +14688,84 @@ components: # Carta Porte Complemento CartaPorteProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: carta_porte - type: object properties: data: $ref: "#/components/schemas/CartaPorteDataProperties" CartaPorteInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: carta_porte - type: object properties: data: $ref: "#/components/schemas/CartaPorteDataInput" ComercioExteriorProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: comercio_exterior - type: object properties: data: $ref: "#/components/schemas/ComercioExteriorDataProperties" ComercioExteriorInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: comercio_exterior - type: object properties: data: $ref: "#/components/schemas/ComercioExteriorDataInput" LeyendasFiscalesProperties: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementProperties" + - type: object + required: + - type + - data + properties: + type: + type: string + const: leyendas_fiscales - type: object properties: data: $ref: "#/components/schemas/LeyendasFiscalesData" LeyendasFiscalesInput: allOf: - - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + - type: object + required: + - type + - data + properties: + type: + type: string + const: leyendas_fiscales - type: object properties: data: @@ -14512,6 +14789,12 @@ components: - leyendas_fiscales - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/CartaPorteProperties" + - $ref: "#/components/schemas/ComercioExteriorProperties" + - $ref: "#/components/schemas/LeyendasFiscalesProperties" + - $ref: "#/components/schemas/CustomComplementProperties" + CartaPorteOrCustomComplementInput: title: Complement type: object @@ -14534,6 +14817,12 @@ components: - leyendas_fiscales - custom description: Tipo de complemento. + oneOf: + - $ref: "#/components/schemas/CartaPorteInput" + - $ref: "#/components/schemas/ComercioExteriorInput" + - $ref: "#/components/schemas/LeyendasFiscalesInput" + - $ref: "#/components/schemas/CustomComplementInput" + LeyendasFiscalesData: type: object title: LeyendasFiscales @@ -15168,6 +15457,11 @@ components: description: Detalle de pesos y piezas de la mercancía. CartaPorteIdentificacionVehicular: type: object + required: + - ConfigVehicular + - PesoBrutoVehicular + - PlacaVM + - AnioModeloVM properties: ConfigVehicular: type: string @@ -15183,6 +15477,9 @@ components: description: Año modelo del vehículo motor. CartaPorteSeguros: type: object + required: + - AseguraRespCivil + - PolizaRespCivil properties: AseguraRespCivil: type: string @@ -15216,6 +15513,11 @@ components: description: Placa del remolque. CartaPorteAutotransporte: type: object + required: + - PermSCT + - NumPermisoSCT + - IdentificacionVehicular + - Seguros properties: PermSCT: type: string @@ -15564,11 +15866,11 @@ components: exterior: type: string description: Número exterior. - example: 142 + example: "142" interior: type: string description: Número interior. - example: 4 + example: "4" neighborhood: type: string description: Colonia @@ -15584,7 +15886,7 @@ components: zip: type: string description: Código postal - example: 86500 + example: "86500" # Main resources Webhook: @@ -15596,6 +15898,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -15608,25 +15912,45 @@ components: description: | Id de la organización la cual se está dando de alta el webhook. livemode: - type: boolean + type: boolean example: false description: Ambiente en el cual se está dando de alta el webhook. enabled_events: - type: string - example: ["receipt.cancellation_status"] - description: Eventos dados de alta para el webhook. + type: array + example: + - receipt.status_updated + description: | + 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. + items: + type: string + enum: + - 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 + - "*" url: type: string - format: email + format: uri description: Http ruta para el webhook example: http://my-website.com/my/webhook status: type: string - description: Status del webhook + description: Status del webhook enum: - enabled - disabled example: enabled + secret: + type: string + readOnly: true + description: Secreto para verificar las firmas. Se entrega al crear el webhook. + description: + type: string + type: object WebhookCreateInput: title: Webhook allOf: @@ -15639,60 +15963,77 @@ components: type: string description: URL del webhook a dar de alta para recibir notificaciones. example: http://my-website.com/my/webhook + format: uri enabled_events: type: array items: type: string enum: - - "invoice.global_invoice_created" - - "invoice.status_updated" - - "invoice.created_from_dashboard" - - "invoice.cancellation_status_updated" - - "receipt.self_invoice_complete" - - "receipt.status_updated" - - "receipt.cancellation_status_updated" + - 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 description: Los eventos a los que el webhook se suscribirá. - example: ["receipt.self_invoice_complete"] + example: + - receipt.self_invoice_complete + minItems: 1 WebhookCreateEdit: title: Webhook allOf: - type: object required: - enabled_events + - status properties: status: type: string description: Estatus del webhook enum: - - "disabled" - - "enabled" + - disabled + - enabled example: disabled enabled_events: type: array items: type: string enum: - - "invoice.global_invoice_created" - - "invoice.status_updated" - - "invoice.cancellation_status_updated" - - "invoice.created_from_dashboard" - - "receipt.self_invoice_complete" - - "receipt.cancellation_status_updated" - - "receipt.status_updated" + - 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 description: Los eventos a los que el webhook se suscribirá. - example: ["receipt.self_invoice_complete"] + example: + - receipt.self_invoice_complete + minItems: 1 Customer: title: Objeto Customer allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/CustomerNonEditableProperties" - - $ref: "#/components/schemas/CustomerProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/CustomerNonEditableProperties' + - $ref: '#/components/schemas/CustomerProperties' + - type: object + properties: + organization: + description: "ID de la organización a la que pertenece este recurso." + type: string + curp: + type: string + external_id: + type: string CustomerSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -15702,23 +16043,27 @@ components: type: object properties: edit_link: - type: string + type: + - string + - 'null' description: | Enlace a una página alojada donde el cliente puede editar su información una vez. Ejemplo: https://auto.facturapi.io/tax-info/abcdWXYZ1234 example: https://auto.facturapi.io/tax-info/abcdWXYZ1234 edit_link_expires_at: - type: string + type: + - string + - 'null' format: date-time description: | Fecha de expiración del enlace de edición. - example: 2022-12-31T23:59:59Z + example: '2022-12-31T23:59:59Z' sat_validated_at: - type: string + type: [string, "null"] format: date-time description: | Fecha en la que la información fiscal fue validado por el SAT. - example: 2022-12-31T23:59:59Z + example: '2022-12-31T23:59:59Z' CustomerProperties: allOf: - $ref: "#/components/schemas/CustomerCommonProperties" @@ -15748,12 +16093,16 @@ components: Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). example: Dunder Mifflin tax_id: - type: string + type: + - string + - 'null' example: ABC101010111 description: 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_system: - type: string - example: "601" + type: + - string + - 'null' + example: '601' maxLength: 3 minLength: 3 description: Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). @@ -15763,47 +16112,206 @@ components: description: Dirección de correo electrónico al cual enviar las facturas generadas. example: email@example.com phone: + type: + - string + - 'null' + description: Teléfono del cliente. + example: '6474010101' + default_invoice_use: + type: string + description: Uso de CFDI por defecto. + example: G01 + CancellationQueryInput: + description: Omite los parámetros para eliminar un borrador. Los documentos emitidos requieren motivo; los motivos 01 y 04 también requieren substitution. + anyOf: + - title: Sustitución requerida + type: object + required: + - motive + - substitution + properties: + motive: + type: string + enum: + - '01' + - '04' + substitution: + type: string + description: ID de Facturapi o UUID del documento sustituto. + - title: Otros motivos de cancelación + type: object + required: + - motive + properties: + motive: + type: string + enum: + - '02' + - '03' + substitution: + type: string + - title: Eliminar borrador + type: object + properties: + motive: false + substitution: false + CustomerCreateWithEditLinkInput: + title: Customer with edit link + description: La información del cliente puede estar incompleta cuando createEditLink=true. Los campos enviados deben conservar formatos válidos. + allOf: + - $ref: '#/components/schemas/CustomerProperties' + - type: object + properties: + tax_system: + type: string + description: Si se envía, debe ser un régimen fiscal válido. Omitirlo permite guardar información fiscal incompleta. + CustomerCreateCommonInput: + type: object + required: + - legal_name + properties: + legal_name: + type: string + description: | + Nombre Fiscal o Razón Social del cliente. *sin* el régimen societario (ej.: S.A. de C.V.). + example: Dunder Mifflin + email: type: string + format: email + description: Dirección de correo electrónico al cual enviar las facturas generadas. + example: email@example.com + phone: + type: + - string + - 'null' description: Teléfono del cliente. - example: 6474010101 + example: '6474010101' default_invoice_use: type: string description: Uso de CFDI por defecto. example: G01 - CustomerCreateInput: - title: Customer + CustomerNationalAddressInput: + allOf: + - $ref: '#/components/schemas/CommonAddressProperties' + - type: object + properties: + state: + type: string + country: + type: string + const: MEX + default: MEX + required: + - zip + CustomerForeignAddressInput: + allOf: + - $ref: '#/components/schemas/CommonAddressProperties' + - type: object + required: + - country + properties: + country: + type: string + not: + const: MEX + minLength: 3 + maxLength: 3 + description: Código ISO 3166-1 alpha-3 distinto de MEX. Es necesario para aplicar las reglas de cliente extranjero. + state: + type: string + CustomerNationalCreateInput: + title: Cliente nacional + description: País MEX, u omitido. Requiere razón social, RFC, régimen fiscal y código postal. Los RFC genéricos usan CustomerGenericCreateInput. allOf: - - $ref: "#/components/schemas/CustomerCommonProperties" + - $ref: '#/components/schemas/CustomerCreateCommonInput' - type: object required: - - legal_name - - tax_id - - tax_system - - address + - tax_id + - tax_system + - address properties: + tax_id: + type: string + example: ABC101010111 + description: 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. + not: + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: string + example: '601' + maxLength: 3 + minLength: 3 + description: Requerido para clientes nacionales. Clave del régimen fiscal del cliente, del catálogo de [Regímenes Fiscales](#r%C3%A9gimen-fiscal). address: - allOf: - - $ref: "#/components/schemas/CommonAddressProperties" - - type: object - description: Domicilio fiscal. - required: - - zip - properties: - state: - type: string - description: 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). - example: Sonora - country: - type: string - description: 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). - example: MEX - default: MEX + $ref: '#/components/schemas/CustomerNationalAddressInput' + CustomerForeignCreateInput: + title: Cliente extranjero + description: 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. + allOf: + - $ref: '#/components/schemas/CustomerCreateCommonInput' + - type: object + required: + - address + properties: + tax_id: + type: + - string + - 'null' + description: 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. + not: + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: + - string + - 'null' + enum: + - '616' + - null + - '' + default: '616' + description: Los clientes extranjeros usan 616. Omitirlo, enviar null o una cadena vacía usa el valor predeterminado. + address: + $ref: '#/components/schemas/CustomerForeignAddressInput' + CustomerGenericCreateInput: + title: RFC genérico + description: 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. + allOf: + - $ref: '#/components/schemas/CustomerCreateCommonInput' + - type: object + required: + - tax_id + properties: + tax_id: + type: string + enum: + - XAXX010101000 + - XEXX010101000 + tax_system: + type: string + enum: + - '616' + default: '616' + address: + anyOf: + - $ref: '#/components/schemas/CustomerNationalAddressInput' + - $ref: '#/components/schemas/CustomerForeignAddressInput' + CustomerCreateInput: + title: Customer + description: Los campos requeridos dependen del país y del RFC. Omitir el país equivale a México. Con createEditLink=true se usa CustomerCreateWithEditLinkInput. + anyOf: + - $ref: '#/components/schemas/CustomerNationalCreateInput' + - $ref: '#/components/schemas/CustomerForeignCreateInput' + - $ref: '#/components/schemas/CustomerGenericCreateInput' LineItemProductInput: title: Product allOf: - $ref: "#/components/schemas/ProductProperties" - + LineItemProductEgresoInput: title: Product allOf: @@ -15822,7 +16330,7 @@ components: product_key: type: string description: 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). - example: 60131324 + example: "60131324" unit_key: type: string default: H87 @@ -15874,33 +16382,41 @@ components: type: string description: Números de pedimento aduanal asociados a esta parte. PartInput: + required: + - description + - product_key allOf: - - type: object - required: - - description - - product_key - $ref: "#/components/schemas/Parts" Product: title: Objeto Product allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/ProductProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/ProductProperties' + - type: object + properties: + organization: + description: "ID de la organización a la que pertenece este recurso." + type: string + required: + - organization + - unit_key ProductSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array items: $ref: "#/components/schemas/Product" ProductProperties: + allOf: + - $ref: "#/components/schemas/ProductEditableProperties" + required: [description, product_key, price] + ProductEditableProperties: type: object - required: - - description - - product_key - - unit_key - - price properties: description: type: string @@ -15909,7 +16425,7 @@ components: product_key: type: string description: 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). - example: 60131324 + example: "60131324" price: type: number description: Precio por unidad del bien o servicio. Este valor representará el precio con IVA incluido o sin él, dependiendo del valor de `tax_included`. @@ -15992,9 +16508,9 @@ components: example: Ukelele product_key: type: string - default: 84111506 + default: "84111506" description: 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). - example: 84111506 + example: "84111506" price: type: number description: Suma total de la cantidad devuelta, descontada o bonificada. @@ -16136,22 +16652,16 @@ components: description: Indica si el impuesto es una retención (`true`) o un traslado (`false`). taxability: type: string - default: | - '01' si el array `taxes` está vacío; '02' si el array `taxes` tiene por lo menos un elemento. enum: - "01" - "02" - "03" - "04" - "05" - description: | - 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" + - "07" + - "08" + description: "Código que representa si el bien o servicio es objeto de impuesto o no. Este atributo corresponde al campo \"ObjetoImp\" en el CFDI.\n\n- `01`: No objeto de impuesto.\n- `02`: Sí objeto de impuesto.\n- `03`: Sí objeto de impuesto, pero no obligado a desglose.\n- `04`: Sí objeto de impuesto, y no causa impuesto.\n- `05`: Sí objeto de impuesto, IVA crédito PODEBI.\n- `06`: Sí objeto de impuesto, no IVA trasladado.\n- `07`: No traslado de IVA, pero desglose de IEPS.\n- `08`: No traslado de IVA sin desglose de IEPS.\n\nSi se omite, se utiliza `01` cuando `taxes` está vacío y `02` cuando contiene al menos un impuesto." installment: type: integer @@ -16173,7 +16683,7 @@ components: type: integer description: Opcionalmente se puede incluir el número de folio del documento relacionado. series: - type: string + type: [string, "null"] description: Opcionalmente se puede incluir la serie del documento relacionado. currency: type: string @@ -16188,8 +16698,7 @@ components: date: type: string format: date-time - default: now - description: Fecha en que se recibió el pago. Sólo es necesario incluirla si el pago se efectuó en una fecha anterior a la emisión de este comprobante. No se permiten fechas futuras. + description: "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." numOperacion: type: string description: 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. @@ -16211,7 +16720,7 @@ components: tipoCadPago: type: string enum: - - 01 + - "01" description: | 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`. @@ -16251,6 +16760,12 @@ components: format: ISO 3166-1 alpha-3 description: Código de País acorde al estándar ISO 3166-1 alpha-3, del Catálogo de Países. example: MEX + zip: + type: string + tax_system: + type: + - string + - 'null' CustomerComercioExterior: type: object description: 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'). @@ -16260,11 +16775,10 @@ components: description: ID del objeto `customer` relacionado a la factura, en caso de no haber sido eliminado example: 58e93bd8e86eb318b0197456 RelatedDocumentInput: + required: + - relationship + - related allOf: - - type: object - required: - - relationship - - related - $ref: '#/components/schemas/RelatedDocument' RelatedDocument: type: object @@ -16296,11 +16810,11 @@ components: InvoiceZipRequestInvoiceType: type: string enum: - - I - - E - - T - - N - - P + - "I" + - "E" + - "T" + - "N" + - "P" description: Tipo de factura (`I` Ingreso, `E` Egreso, `T` Traslado, `N` Nómina o `P` Pago). InvoiceZipRequestCreateInput: type: object @@ -16335,7 +16849,7 @@ components: InvoiceZipRequest: title: Objeto InvoiceZipRequest allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' - type: object required: - organization @@ -16358,13 +16872,13 @@ components: description: Identificador de la organización. example: 65a1f0000000000000000000 issuer_type: - $ref: "#/components/schemas/IssuingType" + $ref: '#/components/schemas/IssuingType' invoice_types: type: array description: Tipos normalizados de las facturas incluidas. uniqueItems: true items: - $ref: "#/components/schemas/InvoiceZipRequestInvoiceType" + $ref: '#/components/schemas/InvoiceZipRequestInvoiceType' example: - E - I @@ -16372,14 +16886,14 @@ components: type: string format: date-time description: Inicio inclusivo del mes solicitado. - example: "2025-03-01T06:00:00.000Z" + example: '2025-03-01T06:00:00.000Z' end_date: type: string format: date-time description: Fin inclusivo del mes solicitado. - example: "2025-04-01T04:59:59.999Z" + example: '2025-04-01T04:59:59.999Z' status: - $ref: "#/components/schemas/InvoiceZipRequestStatus" + $ref: '#/components/schemas/InvoiceZipRequestStatus' document_count: type: integer minimum: 0 @@ -16400,7 +16914,11 @@ components: type: string format: date-time description: Fecha en que se programó el procesamiento. - example: "2026-08-04T18:00:01.000Z" + example: '2026-08-04T18:00:01.000Z' + processing_started_at: + type: string + format: date-time + description: Momento en que comenzó el procesamiento, si existe. InvoiceZipRequestSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" @@ -16429,6 +16947,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -16442,6 +16962,8 @@ components: - price InvoiceProperties: type: object + required: + - date properties: status: type: string @@ -16462,26 +16984,30 @@ components: - accepted - rejected - expired + - verifying description: | 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)). example: none canceled_at: - type: string + type: + - string + - 'null' format: date-time - description: Fecha en la que se canceló el CFDI con hora aproximada. + description: Fecha en la que se canceló el CFDI con hora aproximada. verification_url: type: string format: uri description: 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. example: https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=45BEC0CA-5F1E-491E-9417-698EA48C382A&re=AAA010101AAA&rr=ABC101010111&tt=345.600000&fe=bWApPw== date: - type: string + type: + - string + - 'null' format: date-time - default: now - description: Fecha de expedición del comprobante en formato ISO8601 (UTC String). + description: Fecha de expedición en formato ISO8601. Puede ser null en borradores. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: '#/components/schemas/CommonAddressProperties' - type: object description: Domicilio de expedición de la factura. properties: @@ -16492,15 +17018,17 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. customer: - $ref: "#/components/schemas/CustomerInfo" + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' total: type: number description: Monto total facturado. @@ -16527,7 +17055,7 @@ components: payment_form: type: string description: Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). - example: 06 + example: "06" total_payment_amount: type: number description: Total del complemento de Pago cuando la factura es tipo P. @@ -16548,12 +17076,12 @@ components: type: array description: Conceptos incluidos en el comprobante items: - $ref: "#/components/schemas/LineItem" + $ref: '#/components/schemas/LineItem' related_documents: type: array description: Documentos relacionados con la factura. items: - $ref: "#/components/schemas/RelatedDocument" + $ref: '#/components/schemas/RelatedDocument' received_payment_ids: type: array items: @@ -16586,7 +17114,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + $ref: '#/components/schemas/InvoiceComplementProperties' description: Complementos a incluir en la factura. pdf_custom_section: type: string @@ -16600,9 +17128,58 @@ components: type: array description: Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' stamp: - $ref: "#/components/schemas/Stamp" + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' + organization: + description: "ID de la organización a la que pertenece este recurso." + type: + - string + - 'null' + issuer_type: + $ref: '#/components/schemas/IssuingType' + cfdi_version: + type: number + example: 4 + issuer_info: + $ref: '#/components/schemas/CustomerInfo' + payment_method: + type: string + enum: + - PUE + - PPD + use: + type: string + amount_due: + type: number + verification_carta_porte: + type: string + format: uri + conditions: + type: string + export: + type: string + global: + type: object + required: + - periodicity + - months + - year + properties: + periodicity: + type: string + enum: + - day + - week + - fortnight + - month + - two_months + months: + type: string + year: + type: integer InvoiceDraftProperties: type: object properties: @@ -16624,6 +17201,7 @@ components: - accepted - rejected - expired + - verifying description: | 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)). example: none @@ -16631,15 +17209,16 @@ components: type: string format: uri description: 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. - example: null date: - type: string + type: + - string + - 'null' format: date-time example: null description: Fecha de timbrado del comprobante en formato ISO8601 (UTC String). Si el estado es `draft`, este campo es nulo. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: '#/components/schemas/CommonAddressProperties' - type: object description: Domicilio de expedición de la factura. properties: @@ -16650,24 +17229,26 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. customer: - $ref: "#/components/schemas/CustomerInfo" + description: Cliente de la factura. Es null cuando el borrador no tiene cliente. + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' total: type: number description: Monto total facturado. example: 0 uuid: - type: string + type: [string, "null"] format: uuid - description: Folio fiscal de la factura, asignado por el SAT, en caso de haber sido timbrada. - example: 0 + description: Folio fiscal asignado por el SAT. En un borrador sin timbrar, este campo es null o se omite. folio_number: type: integer description: Número de folio autoincremental para control interno y sin validez fiscal. @@ -16685,17 +17266,17 @@ components: payment_form: type: string description: Código que representa la forma de pago, de acuerdo al [catálogo del SAT](#forma-de-pago). - example: 06 + example: "06" items: type: array description: Conceptos incluidos en el comprobante items: - $ref: "#/components/schemas/LineItem" + $ref: '#/components/schemas/LineItem' related_documents: type: array description: Documentos relacionados con la factura. items: - $ref: "#/components/schemas/RelatedDocument" + $ref: '#/components/schemas/RelatedDocument' currency: type: string example: MXN @@ -16709,7 +17290,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/NominaOrCustomComplementProperties" + $ref: '#/components/schemas/InvoiceComplementProperties' description: Complementos a incluir en la factura. pdf_custom_section: type: string @@ -16723,7 +17304,7 @@ components: type: array description: Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' is_ready_to_stamp: type: boolean description: | @@ -16735,17 +17316,16 @@ components: En una factura con status diferente a `draft`, este campo siempre será `false`. stamp: - allOf: - - $ref: "#/components/schemas/Stamp" - - type: object - example: null + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' + example: null InvoiceableCommonInput: type: object properties: folio_number: type: integer - default: autoincremental description: Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. series: type: string @@ -16966,18 +17546,20 @@ components: antiguedad: type: boolean default: false + InvoiceCustomerInput: + description: Cliente receptor de la factura. + oneOf: + - $ref: "#/components/schemas/CustomerCreateInput" + - type: string + title: customer_id + description: ID del objeto 'customer' previamente registrado en Facturapi. + example: 58e93bd8e86eb318b0197456 InvoiceCommonInputProperties: allOf: - type: object properties: customer: - description: Cliente receptor de la factura. - oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" - - type: string - title: customer_id - description: ID del objeto 'customer' previamente registrado en Facturapi. - example: 58e93bd8e86eb318b0197456 + $ref: "#/components/schemas/InvoiceCustomerInput" status: type: string enum: @@ -16994,8 +17576,7 @@ components: date: type: string format: date-time - default: now - description: 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. + description: "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." address: allOf: - $ref: "#/components/schemas/CommonAddressProperties" @@ -17024,21 +17605,13 @@ components: allOf: - type: object properties: - customer: - description: Cliente receptor de la factura. - oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" - - type: string - title: customer_id - description: ID del objeto 'customer' previamente registrado en Facturapi. - example: 58e93bd8e86eb318b0197456 status: type: string enum: - draft description: | - Estado inicial de la factura. Sólo es posible editar una factura con status `draft`, - y no es posible cambiar el status al editar, por lo que el único valor permitido es `draft`. + 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`. example: draft date: type: string @@ -17046,138 +17619,174 @@ components: description: 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. address: allOf: - - $ref: "#/components/schemas/CommonAddressProperties" + - $ref: "#/components/schemas/CommonAddressProperties" + - type: object + description: | + Puedes usar este parámetro para especificar el domicilio de expedición de la factura. + Este campo es opcional y si no se envía, la factura se expedirá con el domicilio de + la organización. + required: + - zip + properties: + state: + type: string + description: Nombre del Estado o Entidad Federativa. + example: Sonora + external_id: + type: string + description: 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. + idempotency_key: + type: string + description: | + 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. + - $ref: "#/components/schemas/InvoiceableCommonEditInput" + InvoiceDraftInputProperties: + allOf: + - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - type: object + properties: + customer: + description: Cliente receptor de la factura. + oneOf: + - type: "null" + - $ref: "#/components/schemas/CustomerCreateInput" + - type: string + title: customer_id + description: ID del objeto 'customer' previamente registrado en Facturapi. + example: 58e93bd8e86eb318b0197456 + InvoiceCreateInput: + type: object + description: Datos de la factura según su tipo y estado inicial. Omite status para timbrar; usa draft para guardar un borrador. + oneOf: + - title: Ingreso + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceIngresoInput' + - type: object + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceIngresoEditInput' + - type: object + required: + - status + properties: + status: + type: string + const: draft + - title: Egreso + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceEgresoInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceEgresoEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft + - title: Pago + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoicePagoInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoicePagoEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft + - title: Nómina + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceNominaInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceNominaEditInput' + - type: object + required: + - status + - type + properties: + status: + type: string + const: draft + - title: Traslado + type: object + oneOf: + - title: pending + allOf: + - $ref: '#/components/schemas/InvoiceTrasladoInput' + - type: object + required: + - type + properties: + status: + type: string + const: pending + default: pending + - title: draft + allOf: + - $ref: '#/components/schemas/InvoiceTrasladoEditInput' - type: object - description: | - Puedes usar este parámetro para especificar el domicilio de expedición de la factura. - Este campo es opcional y si no se envía, la factura se expedirá con el domicilio de - la organización. required: - - zip + - status + - type properties: - state: + status: type: string - description: Nombre del Estado o Entidad Federativa. - example: Sonora - external_id: - type: string - description: 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. - idempotency_key: - type: string - description: | - 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. - - $ref: "#/components/schemas/InvoiceableCommonEditInput" - InvoiceCreateInput: - type: object - oneOf: - - title: Ingreso - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceIngresoInput" - draft: "#/components/schemas/InvoiceIngresoEditInput" - properties: - status: - type: string - enum: - - pending - - draft - default: pending - description: | - 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. - example: draft - - title: Egreso - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceEgresoInput" - draft: "#/components/schemas/InvoiceEgresoEditInput" - properties: - status: - type: string - enum: - - pending - - draft - default: pending - description: | - 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. - example: draft - - title: Pago - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoicePagoInput" - draft: "#/components/schemas/InvoicePagoEditInput" - properties: - status: - type: string - enum: - - pending - - draft - default: pending - description: | - 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. - example: draft - - title: Nómina - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceNominaInput" - draft: "#/components/schemas/InvoiceNominaEditInput" - properties: - status: - type: string - enum: - - pending - - draft - default: pending - description: | - 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. - example: draft - - title: Traslado - discriminator: - propertyName: status - mapping: - pending: "#/components/schemas/InvoiceTrasladoInput" - draft: "#/components/schemas/InvoiceTrasladoEditInput" - properties: - status: - type: string - enum: - - pending - - draft - default: pending - description: | - 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. - example: draft + const: draft InvoiceIngresoInput: title: Ingreso required: - customer - items - payment_form - - use allOf: - type: object properties: @@ -17215,9 +17824,10 @@ components: - `PUE`: Pago en Una sola Exhibición - `PPD`: Pago en Parcialidades o Diferido use: - type: string - default: G01 + type: [string, "null"] description: | + 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. @@ -17255,7 +17865,7 @@ components: properties: periodicity: type: string - + description: | Periodicidad que abarca la factura global. @@ -17299,7 +17909,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | 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`. @@ -17352,7 +17962,7 @@ components: $ref: "#/components/schemas/LineItemEgresoInput" use: type: string - default: G01 + default: G02 description: 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. currency: type: string @@ -17366,7 +17976,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | Complementos a incluir en el comprobante. Puedes incluir cualquier complemento en el comprobante si tú mismo construyes el nodo XML del @@ -17403,9 +18013,17 @@ components: - $ref: "#/components/schemas/ThirdParty" complements: type: array - default: [] + minItems: 1 + contains: + type: object + required: + - type + properties: + type: + type: string + const: pago items: - $ref: "#/components/schemas/PagoOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complementos a incluir en la factura. - $ref: "#/components/schemas/InvoiceCommonInputProperties" InvoiceNominaInput: @@ -17420,12 +18038,20 @@ components: type: type: string enum: - - N + - "N" complements: type: array - default: [] + minItems: 1 + contains: + type: object + required: + - type + properties: + type: + type: string + const: nomina items: - $ref: "#/components/schemas/NominaOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complementos a incluir en la factura. related_documents: type: array @@ -17461,7 +18087,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CartaPorteOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | 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 @@ -17469,13 +18095,13 @@ components: usando el parámetro `pdf_custom_section`. use: type: string - default: G01 + default: S01 description: | 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. currency: type: string - default: MXN + default: XXX description: Código de la moneda, acorde al estándar [ISO 4217](https://es.wikipedia.org/wiki/ISO_4217). exchange: type: number @@ -17497,14 +18123,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + const: "I" + description: "Tipo de comprobante de esta variante de entrada." items: type: array maxItems: 5000 @@ -17516,7 +18136,7 @@ components: items: $ref: "#/components/schemas/LineItemInput" payment_form: - type: string + type: [string, "null"] minLength: 2 maxLength: 2 example: "03" @@ -17532,7 +18152,7 @@ components: - `PUE`: Pago en Una sola Exhibición - `PPD`: Pago en Parcialidades o Diferido use: - type: string + type: [string, "null"] example: G01 description: | Código de Uso CFDI según el catálogo del SAT. Puedes ver los códigos @@ -17611,13 +18231,13 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | 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`. - - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoiceEgresoEditInput: title: Egreso allOf: @@ -17625,14 +18245,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + const: "E" + description: "Tipo de comprobante de esta variante de entrada." payment_form: type: string minLength: 2 @@ -17675,13 +18289,13 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | 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`. - - $ref: "#/components/schemas/InvoiceCommonInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoicePagoEditInput: title: Pago allOf: @@ -17689,14 +18303,8 @@ components: properties: type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + const: "P" + description: "Tipo de comprobante de esta variante de entrada." related_documents: type: array description: Documentos relacionados con la factura. @@ -17714,28 +18322,24 @@ components: complements: type: array items: - $ref: "#/components/schemas/PagoOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complementos a incluir en la factura. - - $ref: "#/components/schemas/InvoiceCommonEditInputProperties" + - $ref: "#/components/schemas/InvoiceDraftInputProperties" InvoiceNominaEditInput: title: Nómina allOf: - type: object properties: + customer: + $ref: "#/components/schemas/InvoiceCustomerInput" type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + const: "N" + description: "Tipo de comprobante de esta variante de entrada." complements: type: array items: - $ref: "#/components/schemas/NominaOrCustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: Complementos a incluir en la factura. related_documents: type: array @@ -17748,16 +18352,12 @@ components: allOf: - type: object properties: + customer: + $ref: "#/components/schemas/InvoiceCustomerInput" type: type: string - enum: - - I - - E - - P - - N - - T - description: | - Tipo de comprobante. Puede tener los valores `"I"`: Ingreso, `"P"`: Pago, `"E"`: Egreso, `"N"`: Nómina, `"T"`: Traslado. + const: "T" + description: "Tipo de comprobante de esta variante de entrada." items: type: array maxItems: 5000 @@ -17771,7 +18371,7 @@ components: complements: type: array items: - $ref: "#/components/schemas/CustomComplementInput" + $ref: "#/components/schemas/InvoiceComplementInput" description: | 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 @@ -17802,21 +18402,29 @@ components: Receipt: title: Objeto Receipt allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/ReceiptProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/ReceiptProperties' + - type: object + properties: + organization: + description: "ID de la organización a la que pertenece este recurso." + type: string ReceiptProperties: allOf: - type: object + required: + - date + - expires_at properties: date: type: string format: date-time - example: 2021-09-10T15:21:23.456Z + example: "2021-09-10T15:21:23.456Z" description: Fecha de emisión del recibo. expires_at: type: string format: date-time - example: 2021-09-17T15:21:23.456Z + example: "2021-09-17T15:21:23.456Z" description: | 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. @@ -17900,7 +18508,7 @@ components: emitir una recibo con más de 5,000 conceptos, prueba dividir la transacción en varios recibos. items: $ref: "#/components/schemas/LineItemInput" - + - $ref: "#/components/schemas/ReceiptEditableProperties" - type: object properties: @@ -17915,7 +18523,7 @@ components: date: type: string format: date-time - example: 2021-09-10T15:21:23.456Z + example: "2021-09-10T15:21:23.456Z" description: Fecha de emisión del recibo. Por defecto se utiliza la fecha actual. payment_form: type: string @@ -17958,6 +18566,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -17990,25 +18600,37 @@ components: description: Condiciones de pago - $ref: "#/components/schemas/InvoiceableCommonInput" GlobalInvoiceInput: + description: 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. + anyOf: + - title: Seleccionar por periodo + allOf: + - $ref: '#/components/schemas/GlobalInvoiceInputProperties' + - type: object + properties: + receipts: false + - title: Seleccionar recibos explícitos + required: + - receipts + - from + - to + allOf: + - $ref: '#/components/schemas/GlobalInvoiceInputProperties' + GlobalInvoiceInputProperties: type: object - required: - - periodicity properties: from: - type: string - format: date - default: Inicio del último periodo - example: 2022-01-01T00:00:00.000 + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-01' description: | 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`. to: - type: string - format: date - default: Fin del último periodo - example: 2022-01-31T23:59:59.999 + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-31' description: | 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, @@ -18016,27 +18638,28 @@ components: en la configuración de recibos de tu organización. Este valor es requerido cuando se envíe el campo `receipts`. periodicity: type: string - default: Propiedad `periodicity` de la configuración de recibos de la organización. enum: - day - week - fortnight - month - two_months - description: | + description: |- 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. months: type: string - default: Mes contenido en el rango de fechas utilizado. - description: | + description: |- 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). - example: "01" + + Si se omite, el mes o bimestre se determina a partir de la fecha inicial y la periodicidad. + example: '01' folio_number: type: integer - default: autoincremental description: | Número de folio asignado por la empresa para control interno. Si se omite, se asignará el valor autoincremental de la organización. @@ -18045,19 +18668,17 @@ components: maxLength: 25 description: Serie. Caracteres designados por la empresa para control interno y sin validez fiscal. date: - type: string - format: date - default: Valor del atributo `to` - example: 2022-01-01T00:00:00.000 - description: | - Fecha de emisión de la factura. + allOf: + - $ref: '#/components/schemas/DateOrDateTime' + example: '2022-01-01' + description: Fecha de emisión de la factura. Si se omite, se utiliza la fecha final (`to`), limitada a la fecha y hora actuales. payment_form: type: string minLength: 2 maxLength: 2 - example: "02" + example: '02' description: | - description: 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. + 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. receipts: type: array description: | @@ -18115,8 +18736,7 @@ components: default: false description: Si es `true`, sólo valida y regresa un resumen sin crear la factura. payment_form: - type: string - nullable: true + type: ["string","null"] minLength: 2 maxLength: 2 example: "03" @@ -18137,13 +18757,13 @@ components: description: Key del recibo. example: ticket_1001 customer: - nullable: true oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" + - $ref: '#/components/schemas/CustomerCreateInput' - type: string title: customer_id description: ID de un cliente previamente registrado en Facturapi. example: 58e93bd8e86eb318b0197456 + - type: 'null' description: | Cliente opcional para renderizar la vista previa. Si lo omites, todos los recibos deben tener asignado el mismo cliente. @@ -18153,13 +18773,83 @@ components: description: Código de Uso CFDI según catálogo del SAT. ToInvoiceSummary: type: object - description: Objeto resumen que regresa cuando `dry_run=true`. + description: Resumen de importes e impuestos de los recibos cuando `dry_run=true`. + required: [subtotal, discount, taxes, total, receipts, payment_form, item_count] + properties: + subtotal: + type: number + discount: + type: number + total: + type: number + receipts: + type: array + items: + type: string + payment_form: + type: string + item_count: + type: integer + taxes: + type: object + required: [totalAdded, totalWithholding, allAdded, allWithholding, localTotalAdded, localTotalWithholding, localAllAdded, localAllWithholding] + properties: + totalAdded: + type: number + totalWithholding: + type: number + localTotalAdded: + type: number + localTotalWithholding: + type: number + allAdded: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + allWithholding: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + localAllAdded: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + localAllWithholding: + type: array + items: + $ref: "#/components/schemas/ReceiptInvoiceSummaryTax" + ReceiptInvoiceSummaryTax: + type: object + required: [factor, withholding, base, amount] + additionalProperties: true + properties: + type: + type: string + rate: + type: number + factor: + type: string + enum: [Tasa, Cuota, Exento] + withholding: + type: boolean + base: + type: number + amount: + type: number + name: + type: string + Retention: title: Objeto Retention allOf: - - $ref: "#/components/schemas/ResourceAutoGeneratedProps" - - $ref: "#/components/schemas/RetentionReadOnlyProperties" - - $ref: "#/components/schemas/RetentionProperties" + - $ref: '#/components/schemas/ResourceAutoGeneratedProps' + - $ref: '#/components/schemas/RetentionReadOnlyProperties' + - $ref: '#/components/schemas/RetentionProperties' + - type: object + properties: + organization: + description: "ID de la organización a la que pertenece este recurso." + type: string RetentionReadOnlyProperties: type: object properties: @@ -18190,9 +18880,13 @@ components: description: Folio fiscal de la retención, asignado por el SAT. example: 39c85a3f-275b-4341-b259-e8971d9f8a94 stamp: - $ref: "#/components/schemas/Stamp" + anyOf: + - $ref: '#/components/schemas/Stamp' + - type: 'null' customer: - $ref: "#/components/schemas/CustomerInfo" + anyOf: + - $ref: '#/components/schemas/CustomerInfo' + - type: 'null' is_ready_to_stamp: type: boolean description: | @@ -18201,15 +18895,19 @@ components: example: false RetentionProperties: type: object + required: + - fecha_exp properties: cve_retenc: type: string - example: 01 + example: "01" description: Clave de la retención o información de pagos de acuerdo al catálogo del SAT. fecha_exp: - type: string + type: + - string + - 'null' format: date-time - example: "2021-09-15T06:03:23.000Z" + example: '2021-09-15T06:03:23.000Z' description: Fecha de expedición del comprobante en formato ISO8601 (UTC String). desc_retenc: type: string @@ -18278,10 +18976,10 @@ components: tipo_pago_ret: type: string enum: - - 01 - - 02 - - 03 - - 04 + - "01" + - "02" + - "03" + - "04" description: | - `01`: Pago definitivo IVA - `02`: Pago definitivo IEPS @@ -18299,7 +18997,7 @@ components: type: array default: [] items: - $ref: "#/components/schemas/CustomComplementData" + $ref: '#/components/schemas/CustomComplementData' description: | Arreglo de complementos a incluir en la factura. Cada elemento contiene un `string` con el código XML del complemento. @@ -18315,11 +19013,13 @@ components: type: array description: Namespaces a insertar en el nodo raíz de la factura. Requerido en `addenda`. items: - $ref: "#/components/schemas/NamespaceProperties" + $ref: '#/components/schemas/NamespaceProperties' RetentionSearchResult: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -18381,16 +19081,15 @@ components: example: draft customer: description: Cliente receptor de la factura. - nullable: true oneOf: - - $ref: "#/components/schemas/CustomerCreateInput" + - $ref: '#/components/schemas/CustomerCreateInput' - type: string title: customer_id description: ID del objeto 'customer' previamente registrado en Facturapi. example: 58e93bd8e86eb318b0197456 + - type: 'null' cve_retenc: - type: string - nullable: true + type: ["string","null"] example: 26 description: Clave de la retención o información de pagos de acuerdo al [catálogo del SAT](#clave-de-retencion). fecha_exp: @@ -18406,8 +19105,7 @@ components: example: R123 description: Identificador alfanumérico para control interno de la empresa y sin relevancia fiscal. periodo: - type: object - nullable: true + type: ["object","null"] description: Información sobre el periodo de la retención. required: - mes_ini @@ -18431,8 +19129,7 @@ components: example: 2021 description: Año o ejercicio fiscal en que se realizó la retención. totales: - type: object - nullable: true + type: ["object","null"] description: Información sobre el total de retenciones efectuadas en el periodo correspondiente. required: - monto_tot_operacion @@ -18484,10 +19181,10 @@ components: tipo_pago_ret: type: string enum: - - 01 - - 02 - - 03 - - 04 + - "01" + - "02" + - "03" + - "04" description: | - `01`: Pago definitivo IVA - `02`: Pago definitivo IEPS @@ -18539,6 +19236,8 @@ components: allOf: - $ref: "#/components/schemas/SearchResult" - type: object + required: + - data properties: data: type: array @@ -18547,25 +19246,30 @@ components: Organization: title: Objeto Organization type: object + required: + - id + - created_at + - certificate + - fiel properties: id: type: string description: ID del objeto - example: "5a2a307be93a2f00129ea035" + example: 5a2a307be93a2f00129ea035 logo_url: type: string format: uri description: URL del logotipo de la organización. - example: "https://storage.googleapis.com/cdn.facturapi.io/organization/6c100efa5c6f5d7db0379ca643476a4183526007/logo.jpg" + example: https://storage.googleapis.com/cdn.facturapi.io/organization/6c100efa5c6f5d7db0379ca643476a4183526007/logo.jpg timezone: type: string description: Zona horaria de la organización, en formato IANA. - example: "America/Mexico_City" + example: America/Mexico_City created_at: type: string format: date-time description: Fecha de registro - example: "2017-05-05T20:55:33.468Z" + example: '2017-05-05T20:55:33.468Z' is_production_ready: type: boolean description: Indica si la organización tiene información necesaria para facturar en ambiente Live. @@ -18599,7 +19303,7 @@ components: Nombre Fiscal o Razón Social de la organización, *sin* el régimen societario (ej.: S.A. de C.V.). tax_system: type: string - example: "601" + example: '601' maxLength: 3 minLength: 3 description: Código de Régimen Fiscal, del [catálogo del SAT](#régimen-fiscal). @@ -18613,7 +19317,7 @@ components: allOf: - type: object description: Domicilio fiscal de la organización. - - $ref: "#/components/schemas/OrganizationAddress" + - $ref: '#/components/schemas/OrganizationAddress' customization: type: object description: | @@ -18731,16 +19435,16 @@ components: updated_at: type: string format: date-time - example: "2023-05-05T20:55:33.468Z" - description: Fecha de la última actualización del certificado. + example: '2023-05-05T20:55:33.468Z' + description: Fecha de la última actualización del certificado. Se omite cuando no hay un certificado cargado. expires_at: type: string format: date-time - example: "2025-05-05T20:55:33.468Z" - description: Fecha de expiración del certificado. + example: '2025-05-05T20:55:33.468Z' + description: Fecha de expiración del certificado. Se omite cuando no hay un certificado cargado. serial_number: type: string - example: "30001000000300000101" + example: '30001000000300000101' description: Número de serie del certificado CSD. fiel: type: object @@ -18752,16 +19456,16 @@ components: updated_at: type: string format: date-time - example: "2023-05-05T20:55:33.468Z" - description: Fecha de la última actualización del certificado FIEL. + example: '2023-05-05T20:55:33.468Z' + description: Fecha de la última actualización del certificado FIEL. Se omite cuando no hay un certificado cargado. expires_at: type: string format: date-time - example: "2025-05-05T20:55:33.468Z" - description: Fecha de expiración del certificado FIEL. + example: '2025-05-05T20:55:33.468Z' + description: Fecha de expiración del certificado FIEL. Se omite cuando no hay un certificado cargado. serial_number: type: string - example: "30001000000300000101" + example: '30001000000300000101' description: Número de serie del certificado FIEL. receipts: type: object @@ -18839,6 +19543,45 @@ components: type: boolean description: | 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. + plan: + type: + - string + - 'null' + deprecated: true + description: Plan heredado de la organización. + add_ons: + type: array + description: Funcionalidades adicionales contratadas por la organización. + items: + type: string + pending_plan_update: + type: + - object + - 'null' + description: Cambio de plan programado, si existe. + properties: + plan: + type: string + scheduled_for: + type: string + format: date-time + pending_add_ons_update: + type: + - object + - 'null' + description: Cambio programado de funcionalidades adicionales, si existe. + properties: + add_ons: + type: array + items: + type: string + scheduled_for: + type: string + format: date-time + domain: + type: string + custom_domain: + type: string OrganizationDeleteCerts: type: object @@ -19163,11 +19906,11 @@ components: type: type: string enum: - - I - - E - - P - - N - - T + - "I" + - "E" + - "P" + - "N" + - "T" description: | Tipo de comprobante. Valores posibles: `I` (Ingreso), `E` (Egreso), `P` (Pago), `N` (Nómina), `T` (Traslado). @@ -19202,6 +19945,9 @@ components: example: true OrganizationInvite: type: object + required: + - created_at + - expires_at properties: id: type: string @@ -19218,12 +19964,10 @@ components: type: string description: Nombre de la organización que envió la invitación. role: - type: string - nullable: true + type: ["string","null"] description: ID del rol asignado en la invitación, si existe. role_name: - type: string - nullable: true + type: ["string","null"] description: Nombre del rol asignado en la invitación, si existe. roles: type: array @@ -19231,9 +19975,8 @@ components: items: type: string expires_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Fecha y hora en que expira la invitación. OrganizationInviteList: type: array @@ -19242,6 +19985,9 @@ components: $ref: "#/components/schemas/OrganizationInvite" OrganizationPermissionRole: type: object + required: + - created_at + - updated_at properties: id: type: string @@ -19250,12 +19996,10 @@ components: type: string description: Nombre del rol. template_code: - type: string - nullable: true + type: ["string","null"] description: Código de plantilla base del rol, si proviene de una plantilla del sistema. organization: - type: string - nullable: true + type: ["string","null"] description: ID de la organización a la que pertenece el rol. used_by: type: integer @@ -19276,14 +20020,12 @@ components: items: type: string created_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Fecha y hora de creación del rol. updated_at: - type: string + type: ["string","null"] format: date-time - nullable: true description: Fecha y hora de la última actualización del rol. OrganizationPermissionRoleList: type: array @@ -19322,6 +20064,9 @@ components: type: string OrganizationUserAccess: type: object + required: + - created_at + - updated_at properties: id: type: string @@ -19334,16 +20079,13 @@ components: format: email description: Correo electrónico del usuario. role: - type: string - nullable: true + type: ["string","null"] description: ID del rol asignado al usuario, si existe. Para el propietario, este valor es `null` porque su acceso es implícito. role_name: - type: string - nullable: true + type: ["string","null"] description: Nombre del rol asignado o del acceso implícito del usuario. Para el propietario, este valor es `owner`. organization: - type: string - nullable: true + type: ["string","null"] description: ID de la organización a la que pertenece el acceso. operations: type: array @@ -19393,14 +20135,14 @@ components: type: string description: Nombre del rol. template_code: - type: string - nullable: true + type: ["string","null"] enum: - org-admin - org-readonly - org-billing - org-developer - org-team-manager + - null description: Código de plantilla base para inicializar el rol, si aplica. add: type: array @@ -19419,14 +20161,14 @@ components: type: string description: Nuevo nombre del rol. template_code: - type: string - nullable: true + type: ["string","null"] enum: - org-admin - org-readonly - org-billing - org-developer - org-team-manager + - null description: Nuevo código de plantilla base del rol, si aplica. add: type: array diff --git a/website/package.json b/website/package.json index a1d1e707c..17ed999b3 100644 --- a/website/package.json +++ b/website/package.json @@ -12,12 +12,13 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc" + "typecheck": "tsc", + "test:openapi": "node scripts/check-openapi.mjs" }, "dependencies": { - "@docusaurus/core": "^3.10.1", - "@docusaurus/faster": "^3.10.1", - "@docusaurus/preset-classic": "^3.10.1", + "@docusaurus/core": "^3.10.2", + "@docusaurus/faster": "^3.10.2", + "@docusaurus/preset-classic": "^3.10.2", "@mdx-js/react": "^3.1.0", "clsx": "^2.1.1", "file-loader": "^6.2.0", @@ -25,16 +26,18 @@ "prismjs": "^1.30.0", "react": "^19.1.0", "react-dom": "^19.1.0", - "redocusaurus": "^2.5.0", + "redocusaurus": "^2.5.2", "url-loader": "^4.1.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.10.1", - "@docusaurus/tsconfig": "^3.10.1", - "@docusaurus/types": "^3.10.1", + "@docusaurus/module-type-aliases": "^3.10.2", + "@docusaurus/tsconfig": "^3.10.2", + "@docusaurus/types": "^3.10.2", "@types/react": "^19.1.8", "@types/react-helmet": "^6.1.11", "@types/react-router-dom": "^5.3.3", + "js-yaml": "5.4.2", + "openapi-typescript": "7.13.0", "typescript": "^5.8.3" }, "browserslist": { diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 01dcc1050..34b9c04de 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -4,19 +4,22 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + docusaurus-theme-redoc>redoc: 2.5.4 + importers: .: dependencies: '@docusaurus/core': - specifier: ^3.10.1 - version: 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + specifier: ^3.10.2 + version: 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) '@docusaurus/faster': - specifier: ^3.10.1 - version: 3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) + specifier: ^3.10.2 + version: 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) '@docusaurus/preset-classic': - specifier: ^3.10.1 - version: 3.10.1(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3) + specifier: ^3.10.2 + version: 3.10.2(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3) '@mdx-js/react': specifier: ^3.1.0 version: 3.1.1(@types/react@19.2.17)(react@19.2.7) @@ -39,21 +42,21 @@ importers: specifier: ^19.1.0 version: 19.2.7(react@19.2.7) redocusaurus: - specifier: ^2.5.0 - version: 2.5.0(@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@docusaurus/utils@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) + specifier: ^2.5.2 + version: 2.5.2(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@docusaurus/utils@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) url-loader: specifier: ^4.1.1 version: 4.1.1(file-loader@6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) devDependencies: '@docusaurus/module-type-aliases': - specifier: ^3.10.1 - version: 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^3.10.2 + version: 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@docusaurus/tsconfig': - specifier: ^3.10.1 - version: 3.10.1 + specifier: ^3.10.2 + version: 3.10.2 '@docusaurus/types': - specifier: ^3.10.1 - version: 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^3.10.2 + version: 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/react': specifier: ^19.1.8 version: 19.2.17 @@ -63,12 +66,22 @@ importers: '@types/react-router-dom': specifier: ^5.3.3 version: 5.3.3 + js-yaml: + specifier: 5.4.2 + version: 5.4.2 + openapi-typescript: + specifier: 7.13.0 + version: 7.13.0(typescript@5.9.3) typescript: specifier: ^5.8.3 version: 5.9.3 packages: + '@11ty/gray-matter@1.0.0': + resolution: {integrity: sha512-7mJJl+wf1AByoT0PknQiQfOPnVNT4fevGrUBVWO4HXsnYn1aQPyRyrELYrNUFleUBM++KzMKN6QaxHPk0t/6/g==} + engines: {node: '>=11'} + '@algolia/abtesting@1.20.1': resolution: {integrity: sha512-ZXOLrNfmAAhBrIPp+9LH9CDRHUqIx2Uf17YRN6GJ2D0wVPHhCwvMgegCUKQz3W78xVdmzEzjawqf93pPBZVMOg==} engines: {node: '>= 14.0.0'} @@ -1070,12 +1083,12 @@ packages: search-insights: optional: true - '@docusaurus/babel@3.10.1': - resolution: {integrity: sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==} + '@docusaurus/babel@3.10.2': + resolution: {integrity: sha512-aJ1hpGyvfkte3dDAfNbWM4biW4yWZBVz7TIGLZP+v+tWOBgxX3e0N5ZIXHIvmfNNXTI77pcHUx3KmtOk05Ze3Q==} engines: {node: '>=20.0'} - '@docusaurus/bundler@3.10.1': - resolution: {integrity: sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==} + '@docusaurus/bundler@3.10.2': + resolution: {integrity: sha512-i0ZNcy0f0WhaOlYVgzLsWhIoEXO9kS3HRoKPtgE6vQtZUq7arKZaYdNBudr3mqCmd+TyOkwtwfHgs1ENj07r5g==} engines: {node: '>=20.0'} peerDependencies: '@docusaurus/faster': '*' @@ -1083,8 +1096,8 @@ packages: '@docusaurus/faster': optional: true - '@docusaurus/core@3.10.1': - resolution: {integrity: sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==} + '@docusaurus/core@3.10.2': + resolution: {integrity: sha512-EYByj6nk+aD9KeVxV6Hmo2/nAAT79P21Y82ycTBOBtrmqilloIbIEhgL2/8Xpt2Jz/pgNqHAwyusOGwmbKeJmA==} engines: {node: '>=20.0'} hasBin: true peerDependencies: @@ -1096,103 +1109,103 @@ packages: '@docusaurus/faster': optional: true - '@docusaurus/cssnano-preset@3.10.1': - resolution: {integrity: sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==} + '@docusaurus/cssnano-preset@3.10.2': + resolution: {integrity: sha512-4gCnHRbJLTloiwfvFAa92tgb2gI4KYhvjfQVYnEaiMO/EgvWfCo1LwytHXen+1oZAN0VAlS0JAPxp3MsvKDa3A==} engines: {node: '>=20.0'} - '@docusaurus/faster@3.10.1': - resolution: {integrity: sha512-XTZhE5C1gZ/DaYYMlSk02dwP5vhpQON5QHVz1s3892mSESAywgWanURpXEDAvt4GvGuq7s+XP8rTWHZvfaJmdQ==} + '@docusaurus/faster@3.10.2': + resolution: {integrity: sha512-p/5E5/RyHv+QWusJMPN5i3OMJTqTgkhuwzVbB1AReDWTUHXQCmf5mlTFzGiDrWeQWIDOKsuOPn1jJh0s9LUOHA==} engines: {node: '>=20.0'} peerDependencies: '@docusaurus/types': '*' - '@docusaurus/logger@3.10.1': - resolution: {integrity: sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==} + '@docusaurus/logger@3.10.2': + resolution: {integrity: sha512-gSEwqtPfCAnC3ZSJY6xL7tcIfgg0vFD39jbv93eakuweyvO2864xR0K+kmKwBhkTCtWRNjuGGnb5rdmkD/ndqw==} engines: {node: '>=20.0'} - '@docusaurus/mdx-loader@3.10.1': - resolution: {integrity: sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==} + '@docusaurus/mdx-loader@3.10.2': + resolution: {integrity: sha512-9Fd4V/SFjfrVQ0JH5EN0+iPWyFunvTeQE3gfyFeetqPaXMP0OylIjOw16dCuXG4NZJrYdBqwzjh18/h3gRi47w==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/module-type-aliases@3.10.1': - resolution: {integrity: sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==} + '@docusaurus/module-type-aliases@3.10.2': + resolution: {integrity: sha512-h/I5e4jaAhDHW4vaLENi1i2hnOEnXY1t9R+nnRTbgUl7ymVRzN/HF7dDfj8rKYGj8gfIge+Ef+iYRAMtbGvsrQ==} peerDependencies: react: '*' react-dom: '*' - '@docusaurus/plugin-content-blog@3.10.1': - resolution: {integrity: sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==} + '@docusaurus/plugin-content-blog@3.10.2': + resolution: {integrity: sha512-0cbEnNKf0InmLkhj/+nVRmqEnWEoOE8Mh+2x1qOXI0qYpCnphq4RXknVJ8BvybKRXqYVvbmdMfiJSup+k4tm5w==} engines: {node: '>=20.0'} peerDependencies: '@docusaurus/plugin-content-docs': '*' react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-content-docs@3.10.1': - resolution: {integrity: sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==} + '@docusaurus/plugin-content-docs@3.10.2': + resolution: {integrity: sha512-Sqwl4FPoZBDrlY8I2VU2H8O0M91CHp9T8ToMSkTZmjvHCif+1laqfXi6sTk8IfyVS/trN5yNjcWd1bFsGB6W5Q==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-content-pages@3.10.1': - resolution: {integrity: sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==} + '@docusaurus/plugin-content-pages@3.10.2': + resolution: {integrity: sha512-h5R12sZ/vV9EPiVjvIl9YFCOwkpwXes7dQMYt3EvP6Pphu4amHxxTqWxf08Fl5DR8h+oZMbWpFTNw5vKEYfvzQ==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-css-cascade-layers@3.10.1': - resolution: {integrity: sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==} + '@docusaurus/plugin-css-cascade-layers@3.10.2': + resolution: {integrity: sha512-UkdvQby5OQUKWrw3lLnSTJXQ6VETaUVTuPQX9AABtmFm5h+ifEBx1OQ+LN726Q4byuwBf2ElHkf4qU4hTxdvRg==} engines: {node: '>=20.0'} - '@docusaurus/plugin-debug@3.10.1': - resolution: {integrity: sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==} + '@docusaurus/plugin-debug@3.10.2': + resolution: {integrity: sha512-8vbZNOSCpnsT57EY6CgN7sgRVmx3KTYwO8Uvo2pbxOyb8tbqAwtT9SslqaQ41HbA1v1hpn5RP7u5s2KvRwAFpQ==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-analytics@3.10.1': - resolution: {integrity: sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==} + '@docusaurus/plugin-google-analytics@3.10.2': + resolution: {integrity: sha512-kMHMBK9j4VAtgd5owwrRLRIi0EjkrpXlX7ePj1+y68XfVZV9I1T4S+koPDm+Hfw2TtnyHvh0uNrDvjz+DjQGVA==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-gtag@3.10.1': - resolution: {integrity: sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==} + '@docusaurus/plugin-google-gtag@3.10.2': + resolution: {integrity: sha512-Vt90nNFhtAChRe9+it1hcHFgFvETdSnOkL5Bma+p6E/yU2tAYrvvyk+gv+LJGM2ZUkyKuKXLRsZ2Lb0bO7+Vog==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-tag-manager@3.10.1': - resolution: {integrity: sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==} + '@docusaurus/plugin-google-tag-manager@3.10.2': + resolution: {integrity: sha512-MLCffCldysi/R0nzJQP7ZWd0xAoGNnSTiVOo6TTR6mKVGFhE+/XArGe67ZcaZv1uytgQXoXs92VJrgVDrz80rQ==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-sitemap@3.10.1': - resolution: {integrity: sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==} + '@docusaurus/plugin-sitemap@3.10.2': + resolution: {integrity: sha512-PODkwg5XetLML3hU/3xpCKJUZ9cqExLaBnD/Fzzwj2VHogLeqnDisLIujae87zuze7T4mCm2A6KEqZkyiz07EQ==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-svgr@3.10.1': - resolution: {integrity: sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==} + '@docusaurus/plugin-svgr@3.10.2': + resolution: {integrity: sha512-JgfT3jWM0TJ8Uw0cEcqxHpybngQY1vlBYpuuNO+gEh5iPh5Ar+vxq/u9CFrYsWeXy48BN7Db76Pzp2edNXUQ8A==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/preset-classic@3.10.1': - resolution: {integrity: sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==} + '@docusaurus/preset-classic@3.10.2': + resolution: {integrity: sha512-a4B3VczmDl99zK0EufDQYomdJ186WDingjmDXxhN2PNPS9Ty/Y2M5CLFX1KQMRKqRTLiRDKfutzG5IY1FC/ceg==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 @@ -1203,51 +1216,51 @@ packages: peerDependencies: react: '*' - '@docusaurus/theme-classic@3.10.1': - resolution: {integrity: sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==} + '@docusaurus/theme-classic@3.10.2': + resolution: {integrity: sha512-JqTSLQmqmA9uKWZsD5iwBGJ4JyKB4/yTw6PsSXVPRJG/6GAm/u+add9Iip+hvwP12/AnPNztrdxsI14NJW4KeA==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-common@3.10.1': - resolution: {integrity: sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==} + '@docusaurus/theme-common@3.10.2': + resolution: {integrity: sha512-R9b/vMpK1yye6hNZTA6x/ivRv+at6GhxnXcxkpzCGzO1R1RwiquqiFg2wMFh6aqlJTpWRFKpFD2TzCDQcyOU0A==} engines: {node: '>=20.0'} peerDependencies: '@docusaurus/plugin-content-docs': '*' react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-search-algolia@3.10.1': - resolution: {integrity: sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==} + '@docusaurus/theme-search-algolia@3.10.2': + resolution: {integrity: sha512-1msxllyhi/5m77JukXtp5UFnUAriwZIC1oJ7MTnpQpCwLTbclJi5BK5n28CTZuSXpQN2ewbbnqRgAhMM6c6ihg==} engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-translations@3.10.1': - resolution: {integrity: sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==} + '@docusaurus/theme-translations@3.10.2': + resolution: {integrity: sha512-iv20wrxnyXkY89LM3TzRlzGlt5fIGO5UnaR6UL1ZVfB9RRFjxQFQ6awDrwAc6Km8Y5gD8pInuwYPF+6/TiCxXA==} engines: {node: '>=20.0'} - '@docusaurus/tsconfig@3.10.1': - resolution: {integrity: sha512-rYvB7yqkdqWIpAbDzQljGfM4cDBkLTbhmagZBEcsyj6oPUsz47lmW2pYdN1j+7sGFgltbAmQH62xfbrij4Eh6Q==} + '@docusaurus/tsconfig@3.10.2': + resolution: {integrity: sha512-5GiB7h/nFsMFPO9mCqcRNE1yA5TSXXNCshNIgHPL6fCPOjcTDixs6qjQBu8ddkgPcicwCvOA7n3jeK2rGdJk6g==} - '@docusaurus/types@3.10.1': - resolution: {integrity: sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==} + '@docusaurus/types@3.10.2': + resolution: {integrity: sha512-B6rvfwIFSapUqUJjMriZswX13K8l5Z7AcmVE6uTEJpYddQieSTR12DsGaFtcZAIDsQd4p+0WTl0Vc6jmZK0Trw==} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/utils-common@3.10.1': - resolution: {integrity: sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==} + '@docusaurus/utils-common@3.10.2': + resolution: {integrity: sha512-x3Dz6jv6iQKBNjBmVTu8p57abMp/VNTUgKBMgRVXJc5444orBTsArv0+cdfrXTiz/VMmHfDRVkPbL7GH2B7T7w==} engines: {node: '>=20.0'} - '@docusaurus/utils-validation@3.10.1': - resolution: {integrity: sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==} + '@docusaurus/utils-validation@3.10.2': + resolution: {integrity: sha512-sn8unbDfUL585NtR3cwHefPicOyaHvPaX7VD0aOg/siIxUBoKyKKaGEqzJZDS64mM43TnxurkYDtmB1wsJlZsw==} engines: {node: '>=20.0'} - '@docusaurus/utils@3.10.1': - resolution: {integrity: sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==} + '@docusaurus/utils@3.10.2': + resolution: {integrity: sha512-xx0W3eav2uW1NRIpuHJWNwLTC15xPNjU4Uxi9NSnd3swYC96BE3vFiT93SD8s24kmAAWNwgZwfZ2fghGZ01Lcw==} engines: {node: '>=20.0'} '@emnapi/core@1.11.1': @@ -1525,9 +1538,15 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@redocly/ajv@8.11.2': + resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==} + '@redocly/ajv@8.18.3': resolution: {integrity: sha512-l42u0of3hY98sN2A+M4qTX1O/KrpgGH32Hu9kP2GtHyD5Dfqq86PKFLe5dwaD8DEnNmlOlll2BAmeEtf0DaySg==} + '@redocly/config@0.22.0': + resolution: {integrity: sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==} + '@redocly/config@0.6.3': resolution: {integrity: sha512-hGWJgCsXRw0Ow4rplqRlUQifZvoSwZipkYnt11e3SeH1Eb23VUIDBcRuaQOUqy1wn0eevXkU2GzzQ8fbKdQ7Mg==} @@ -1535,6 +1554,10 @@ packages: resolution: {integrity: sha512-z06h+svyqbUcdAaePq8LPSwTPlm6Ig7j2VlL8skPBYnJvyaQ2IN7x/JkOvRL4ta+wcOCBdAex5JWnZbKaNktJg==} engines: {node: '>=14.19.0', npm: '>=7.0.0'} + '@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'} + '@rspack/binding-darwin-arm64@1.7.11': resolution: {integrity: sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig==} cpu: [arm64] @@ -1919,9 +1942,6 @@ packages: '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/gtag.js@0.0.20': - resolution: {integrity: sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -2111,9 +2131,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - address@1.2.2: - resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} - engines: {node: '>= 10.0.0'} + address@2.0.3: + resolution: {integrity: sha512-XNAb/a6TCqou+TufU8/u11HCu9x1gYvOoxLwtlXgIqmkrYQADVv6ljyW2zwiPhHz9R1gItAWpuDrdJMmrOBFEA==} + engines: {node: '>= 16.0.0'} agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} @@ -2159,6 +2179,10 @@ packages: ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-html-community@0.0.8: resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} engines: {'0': node >= 0.8.0} @@ -2194,9 +2218,6 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -2380,6 +2401,9 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} @@ -2789,9 +2813,9 @@ packages: detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - detect-port@1.6.1: - resolution: {integrity: sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==} - engines: {node: '>= 4.0.0'} + detect-port@2.1.0: + resolution: {integrity: sha512-epZuWb/6Q62L+nDHJc/hQAqf8pylsqgk3BpZXVBx1CDnr3nkrVNn73Uu1rXcFzkNcc+hkP3whuOg7JZYaQB65Q==} + engines: {node: '>= 16.0.0'} hasBin: true devlop@1.1.0: @@ -2811,8 +2835,8 @@ packages: peerDependencies: '@docusaurus/utils': ^3.6.0 - docusaurus-theme-redoc@2.5.0: - resolution: {integrity: sha512-ykLmnnvE20Im3eABlIpUnXnT2gSHVAjgyy2fU2G8yecu7zqIE+G/SiBpBg/hrWMUycL31a8VSG7Ehkf3pg1u+A==} + docusaurus-theme-redoc@2.5.1: + resolution: {integrity: sha512-BGbDv748peVQwttDQbhGCnA5eXtcBa76WP+nmc7Vz0bwEJv5Dh9et/WHJBRlFu97ScMS38+WpBnexCvYv3HYww==} engines: {node: '>=18'} peerDependencies: '@docusaurus/theme-common': ^3.6.0 @@ -2955,11 +2979,6 @@ packages: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -3212,10 +3231,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} - gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} @@ -3401,6 +3416,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'} + infima@0.2.0-alpha.45: resolution: {integrity: sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==} engines: {node: '>=12'} @@ -3592,12 +3611,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.2: - resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true - js-yaml@4.2.0: - resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + js-yaml@5.4.2: + resolution: {integrity: sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==} hasBin: true jsesc@3.1.0: @@ -4081,6 +4100,19 @@ packages: react-native: optional: true + mobx-react@9.2.0: + resolution: {integrity: sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw==} + peerDependencies: + mobx: ^6.9.0 + react: ^16.8.0 || ^17 || ^18 || ^19 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + mobx-react@9.2.2: resolution: {integrity: sha512-ShszmQzR/VrhU3M0cQ7DA/s8qNcLcF2emSuudJ/TnDILS3C1Im48mdaG6CpyjZHy8+WqgXUCC9mPqSRIwPPMuQ==} peerDependencies: @@ -4236,6 +4268,12 @@ packages: openapi-sampler@1.7.4: resolution: {integrity: sha512-CKS/rd5ucPCuEDbJnjGDXZTsuGWcmv53aCmQx7soZlPEONUGN4af0/dY5+THRFZraSEjeA78nlfzdFswC/N5SA==} + openapi-typescript@7.13.0: + resolution: {integrity: sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==} + hasBin: true + peerDependencies: + typescript: ^5.x + opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -4290,6 +4328,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'} + parse-numeric-range@1.3.0: resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} @@ -4927,8 +4969,18 @@ packages: react-dom: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0 styled-components: ^4.1.1 || ^5.1.1 || ^6.0.5 - redocusaurus@2.5.0: - resolution: {integrity: sha512-QWJX2hgnEfSDb7fZzS4iZe6aqdAvm/XLCsNv6RkgDw6Pl/lsTZKipP2n1r5QS1CC5hY8eAwsjVXeF7B03vkz2g==} + redoc@2.5.4: + resolution: {integrity: sha512-M6jWhG1qoBnH6TFmzJnstyCZ87HmOY/UzDm78mHiYihEdlV/YcS9ogOo1NlElnJMeLsyxHFe2yFc4sNjHTrABQ==} + engines: {node: '>=6.9', npm: '>=3.0.0'} + peerDependencies: + core-js: ^3.1.4 + mobx: ^6.0.4 + react: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0 + styled-components: ^4.1.1 || ^5.1.1 || ^6.0.5 + + redocusaurus@2.5.2: + resolution: {integrity: sha512-81xELtq+yRW1p+407yroPRvmIDjK5QNldYi5hRAJC1vVPKWm6lzBQ9HihE+51520MuAbZWmNNVa1ml5DhlDd1A==} engines: {node: '>=14'} peerDependencies: '@docusaurus/theme-common': ^3.6.0 @@ -5255,9 +5307,6 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - srcset@4.0.0: resolution: {integrity: sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==} engines: {node: '>=12'} @@ -5355,6 +5404,10 @@ packages: stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + 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'} @@ -5501,6 +5554,10 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -5579,6 +5636,9 @@ packages: resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} engines: {node: '>=14.16'} + uri-js-replace@1.0.1: + resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -5814,6 +5874,13 @@ packages: snapshots: + '@11ty/gray-matter@1.0.0': + dependencies: + js-yaml: 4.3.2 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + '@algolia/abtesting@1.20.1': dependencies: '@algolia/client-common': 5.54.1 @@ -5965,7 +6032,7 @@ snapshots: '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -6017,7 +6084,7 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) lodash.debounce: 4.0.8 resolve: 1.22.12 transitivePeerDependencies: @@ -6693,7 +6760,7 @@ snapshots: '@babel/parser': 7.29.7 '@babel/template': 7.29.7 '@babel/types': 7.29.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -7038,7 +7105,7 @@ snapshots: - '@algolia/client-search' - algoliasearch - '@docusaurus/babel@3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/babel@3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@babel/core': 7.29.7 '@babel/generator': 7.29.7 @@ -7049,8 +7116,8 @@ snapshots: '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) '@babel/runtime': 7.29.7 '@babel/traverse': 7.29.7 - '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/logger': 3.10.2 + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) babel-plugin-dynamic-import-node: 2.3.3 fs-extra: 11.3.5 tslib: 2.8.1 @@ -7072,48 +7139,14 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/babel@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/bundler@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: '@babel/core': 7.29.7 - '@babel/generator': 7.29.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) - '@babel/preset-env': 7.29.7(@babel/core@7.29.7) - '@babel/preset-react': 7.29.7(@babel/core@7.29.7) - '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) - '@babel/runtime': 7.29.7 - '@babel/traverse': 7.29.7 - '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - babel-plugin-dynamic-import-node: 2.3.3 - fs-extra: 11.3.5 - tslib: 2.8.1 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - react - - react-dom - - supports-color - - uglify-js - - webpack-cli - - '@docusaurus/bundler@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': - dependencies: - '@babel/core': 7.29.7 - '@docusaurus/babel': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/cssnano-preset': 3.10.1 - '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/babel': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/cssnano-preset': 3.10.2 + '@docusaurus/logger': 3.10.2 + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) babel-loader: 9.2.1(@babel/core@7.29.7)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) clean-css: 5.3.3 copy-webpack-plugin: 11.0.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) @@ -7133,7 +7166,7 @@ snapshots: webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) webpackbar: 7.0.0(@rspack/core@1.7.11)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) optionalDependencies: - '@docusaurus/faster': 3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) + '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) transitivePeerDependencies: - '@minify-html/node' - '@parcel/css' @@ -7151,15 +7184,15 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/core@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/core@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/babel': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/bundler': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/babel': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/bundler': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mdx-js/react': 3.1.1(@types/react@19.2.17)(react@19.2.7) boxen: 6.2.1 chalk: 4.1.2 @@ -7168,7 +7201,7 @@ snapshots: combine-promises: 1.2.0 commander: 5.1.0 core-js: 3.49.0 - detect-port: 1.6.1 + detect-port: 2.1.0 escape-html: 1.0.3 eta: 2.2.0 eval: 0.1.8 @@ -7194,12 +7227,12 @@ snapshots: tinypool: 1.1.1 tslib: 2.8.1 update-notifier: 6.0.2 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) webpack-bundle-analyzer: 4.10.2 webpack-dev-server: 5.2.5(tslib@2.8.1)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) webpack-merge: 6.0.1 optionalDependencies: - '@docusaurus/faster': 3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) + '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15) transitivePeerDependencies: - '@minify-html/node' - '@parcel/css' @@ -7222,16 +7255,16 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/cssnano-preset@3.10.1': + '@docusaurus/cssnano-preset@3.10.2': dependencies: cssnano-preset-advanced: 6.1.2(postcss@8.5.15) postcss: 8.5.15 postcss-sort-media-queries: 5.2.0(postcss@8.5.15) tslib: 2.8.1 - '@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15)': + '@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15)': dependencies: - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@rspack/core': 1.7.11 '@swc/core': 1.15.41 '@swc/html': 1.15.41 @@ -7254,16 +7287,16 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/logger@3.10.1': + '@docusaurus/logger@3.10.2': dependencies: chalk: 4.1.2 tslib: 2.8.1 - '@docusaurus/mdx-loader@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/mdx-loader@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/logger': 3.10.2 + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mdx-js/mdx': 3.1.1 '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 @@ -7286,7 +7319,7 @@ snapshots: unist-util-visit: 5.1.0 url-loader: 4.1.1(file-loader@6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) vfile: 6.0.3 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - '@minify-html/node' - '@swc/core' @@ -7303,9 +7336,9 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/module-type-aliases@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/module-type-aliases@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/history': 4.7.11 '@types/react': 19.2.17 '@types/react-router-config': 5.0.11 @@ -7330,17 +7363,17 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': - dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/plugin-content-docs': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/plugin-content-blog@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) cheerio: 1.0.0-rc.12 combine-promises: 1.2.0 feed: 4.2.2 @@ -7353,7 +7386,7 @@ snapshots: tslib: 2.8.1 unist-util-visit: 5.1.0 utility-types: 3.11.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -7378,28 +7411,28 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': - dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/module-type-aliases': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.3.5 - js-yaml: 4.2.0 + js-yaml: 4.3.2 lodash: 4.18.1 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) schema-dts: 1.1.5 tslib: 2.8.1 utility-types: 3.11.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -7424,18 +7457,18 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-pages@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-content-pages@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) fs-extra: 11.3.5 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) tslib: 2.8.1 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -7460,12 +7493,12 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-css-cascade-layers@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-css-cascade-layers@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7493,11 +7526,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-debug@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-debug@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) fs-extra: 11.3.5 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -7527,11 +7560,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-analytics@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-google-analytics@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) tslib: 2.8.1 @@ -7559,12 +7592,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-gtag@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-google-gtag@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@types/gtag.js': 0.0.20 + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) tslib: 2.8.1 @@ -7592,11 +7624,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-google-tag-manager@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) tslib: 2.8.1 @@ -7624,14 +7656,14 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-sitemap@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-sitemap@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) fs-extra: 11.3.5 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -7661,18 +7693,18 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-svgr@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + '@docusaurus/plugin-svgr@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/webpack': 8.1.0(typescript@5.9.3) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) tslib: 2.8.1 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -7697,23 +7729,23 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/preset-classic@3.10.1(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3)': - dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-content-docs': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-content-pages': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-css-cascade-layers': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-debug': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-google-analytics': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-google-gtag': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-google-tag-manager': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-sitemap': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-svgr': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/theme-classic': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/theme-search-algolia': 3.10.1(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3) - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/preset-classic@3.10.2(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-content-blog': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-css-cascade-layers': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-debug': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-google-analytics': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-google-gtag': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-google-tag-manager': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-sitemap': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-svgr': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/theme-classic': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-search-algolia': 3.10.2(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) transitivePeerDependencies: @@ -7748,21 +7780,21 @@ snapshots: '@types/react': 19.2.17 react: 19.2.7 - '@docusaurus/theme-classic@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': - dependencies: - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/module-type-aliases': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-content-docs': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/plugin-content-pages': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/theme-translations': 3.10.1 - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-classic@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/plugin-content-blog': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-translations': 3.10.2 + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@mdx-js/react': 3.1.1(@types/react@19.2.17)(react@19.2.7) clsx: 2.1.1 copy-text-to-clipboard: 3.2.2 @@ -7801,13 +7833,13 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/mdx-loader': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/module-type-aliases': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/plugin-content-docs': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/history': 4.7.11 '@types/react': 19.2.17 '@types/react-router-config': 5.0.11 @@ -7834,17 +7866,17 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.10.1(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3)': + '@docusaurus/theme-search-algolia@3.10.2(@algolia/client-search@5.54.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(@types/react@19.2.17)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(typescript@5.9.3)': dependencies: '@algolia/autocomplete-core': 1.19.8(@algolia/client-search@5.54.1)(algoliasearch@5.54.1)(search-insights@2.17.3) '@docsearch/react': 4.6.3(@algolia/client-search@5.54.1)(@types/react@19.2.17)(algoliasearch@5.54.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3) - '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/logger': 3.10.1 - '@docusaurus/plugin-content-docs': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/theme-translations': 3.10.1 - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/logger': 3.10.2 + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-translations': 3.10.2 + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) algoliasearch: 5.54.1 algoliasearch-helper: 3.29.1(algoliasearch@5.54.1) clsx: 2.1.1 @@ -7882,14 +7914,14 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-translations@3.10.1': + '@docusaurus/theme-translations@3.10.2': dependencies: fs-extra: 11.3.5 tslib: 2.8.1 - '@docusaurus/tsconfig@3.10.1': {} + '@docusaurus/tsconfig@3.10.2': {} - '@docusaurus/types@3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/types@3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@mdx-js/mdx': 3.1.1 '@types/history': 4.7.11 @@ -7919,61 +7951,9 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@mdx-js/mdx': 3.1.1 - '@types/history': 4.7.11 - '@types/mdast': 4.0.4 - '@types/react': 19.2.17 - commander: 5.1.0 - joi: 17.13.4 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)' - utility-types: 3.11.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) - webpack-merge: 5.10.0 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - supports-color - - uglify-js - - webpack-cli - - '@docusaurus/utils-common@3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - tslib: 2.8.1 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - react - - react-dom - - supports-color - - uglify-js - - webpack-cli - - '@docusaurus/utils-common@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/utils-common@3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) tslib: 2.8.1 transitivePeerDependencies: - '@minify-html/node' @@ -7993,14 +7973,14 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils-validation@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/utils-validation@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/logger': 3.10.2 + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) fs-extra: 11.3.5 joi: 17.13.4 - js-yaml: 4.2.0 + js-yaml: 4.3.2 lodash: 4.18.1 tslib: 2.8.1 transitivePeerDependencies: @@ -8021,20 +8001,20 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@docusaurus/utils@3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@11ty/gray-matter': 1.0.0 + '@docusaurus/logger': 3.10.2 + '@docusaurus/types': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) escape-string-regexp: 4.0.0 execa: 5.1.1 file-loader: 6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) fs-extra: 11.3.5 github-slugger: 1.5.0 globby: 11.1.0 - gray-matter: 4.0.3 jiti: 1.21.7 - js-yaml: 4.2.0 + js-yaml: 4.3.2 lodash: 4.18.1 micromatch: 4.0.8 p-queue: 6.6.2 @@ -8062,47 +8042,6 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - escape-string-regexp: 4.0.0 - execa: 5.1.1 - file-loader: 6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) - fs-extra: 11.3.5 - github-slugger: 1.5.0 - globby: 11.1.0 - gray-matter: 4.0.3 - jiti: 1.21.7 - js-yaml: 4.2.0 - lodash: 4.18.1 - micromatch: 4.0.8 - p-queue: 6.6.2 - prompts: 2.4.2 - resolve-pathname: 3.0.0 - tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) - utility-types: 3.11.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - react - - react-dom - - supports-color - - uglify-js - - webpack-cli - '@emnapi/core@1.11.1': dependencies: '@emnapi/wasi-threads': 1.2.2 @@ -8491,6 +8430,13 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@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 + '@redocly/ajv@8.18.3': dependencies: fast-deep-equal: 3.1.3 @@ -8498,6 +8444,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + '@redocly/config@0.22.0': {} + '@redocly/config@0.6.3': {} '@redocly/openapi-core@1.16.0': @@ -8505,9 +8453,9 @@ snapshots: '@redocly/ajv': 8.18.3 '@redocly/config': 0.6.3 colorette: 1.4.0 - https-proxy-agent: 7.0.6 + https-proxy-agent: 7.0.6(supports-color@10.2.2) js-levenshtein: 1.1.6 - js-yaml: 4.2.0 + js-yaml: 4.3.2 lodash.isequal: 4.5.0 minimatch: 5.1.9 node-fetch: 2.7.0 @@ -8517,6 +8465,20 @@ snapshots: - encoding - supports-color + '@redocly/openapi-core@1.34.20(supports-color@10.2.2)': + dependencies: + '@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 + '@rspack/binding-darwin-arm64@1.7.11': optional: true @@ -8857,8 +8819,6 @@ snapshots: '@types/qs': 6.15.1 '@types/serve-static': 1.15.10 - '@types/gtag.js@0.0.20': {} - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -8938,7 +8898,7 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 17.0.45 + '@types/node': 25.9.3 '@types/send@0.17.6': dependencies: @@ -9081,7 +9041,7 @@ snapshots: acorn@8.17.0: {} - address@1.2.2: {} + address@2.0.3: {} agent-base@7.1.4: {} @@ -9143,6 +9103,8 @@ snapshots: dependencies: string-width: 4.2.3 + ansi-colors@4.1.3: {} + ansi-html-community@0.0.8: {} ansi-regex@5.0.1: {} @@ -9166,10 +9128,6 @@ snapshots: arg@5.0.2: {} - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - argparse@2.0.1: {} array-flatten@1.1.1: {} @@ -9198,7 +9156,7 @@ snapshots: '@babel/core': 7.29.7 find-cache-dir: 4.0.0 schema-utils: 4.3.3 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) babel-plugin-dynamic-import-node@2.3.3: dependencies: @@ -9387,6 +9345,8 @@ snapshots: chalk@5.6.2: {} + change-case@5.4.4: {} + char-regex@1.0.2: {} character-entities-html4@2.1.0: {} @@ -9553,7 +9513,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) core-js-compat@3.49.0: dependencies: @@ -9566,7 +9526,7 @@ snapshots: cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 - js-yaml: 4.2.0 + js-yaml: 4.3.2 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: @@ -9610,7 +9570,7 @@ snapshots: semver: 7.8.4 optionalDependencies: '@rspack/core': 1.7.11 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): dependencies: @@ -9620,7 +9580,7 @@ snapshots: postcss: 8.5.15 schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) optionalDependencies: clean-css: 5.3.3 @@ -9727,9 +9687,11 @@ snapshots: dependencies: ms: 2.0.0 - debug@4.4.3: + debug@4.4.3(supports-color@10.2.2): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 10.2.2 decko@1.2.0: {} @@ -9782,12 +9744,9 @@ snapshots: detect-node@2.1.0: {} - detect-port@1.6.1: + detect-port@2.1.0: dependencies: - address: 1.2.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color + address: 2.0.3 devlop@1.1.0: dependencies: @@ -9801,9 +9760,9 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.5 - docusaurus-plugin-redoc@2.5.0(@docusaurus/utils@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): + docusaurus-plugin-redoc@2.5.0(@docusaurus/utils@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): dependencies: - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@redocly/openapi-core': 1.16.0 redoc: 2.4.0(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) transitivePeerDependencies: @@ -9816,18 +9775,18 @@ snapshots: - styled-components - supports-color - docusaurus-theme-redoc@2.5.0(@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): + docusaurus-theme-redoc@2.5.1(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): dependencies: - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@redocly/openapi-core': 1.16.0 clsx: 1.2.1 lodash: 4.18.1 mobx: 6.16.1 postcss: 8.5.15 postcss-prefix-selector: 1.16.1(postcss@8.5.15) - redoc: 2.4.0(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) + redoc: 2.5.4(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) styled-components: 6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - core-js - css-to-react-native @@ -9970,8 +9929,6 @@ snapshots: esrecurse: 4.3.0 estraverse: 4.3.0 - esprima@4.0.1: {} - esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -10138,7 +10095,7 @@ snapshots: dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) fill-range@7.1.1: dependencies: @@ -10276,13 +10233,6 @@ snapshots: graceful-fs@4.2.11: {} - gray-matter@4.0.3: - dependencies: - js-yaml: 3.14.2 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - gzip-size@6.0.0: dependencies: duplexer: 0.1.2 @@ -10454,7 +10404,7 @@ snapshots: tapable: 2.3.3 optionalDependencies: '@rspack/core': 1.7.11 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) htmlparser2@6.1.0: dependencies: @@ -10519,10 +10469,10 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - https-proxy-agent@7.0.6: + https-proxy-agent@7.0.6(supports-color@10.2.2): dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -10553,6 +10503,8 @@ snapshots: indent-string@4.0.0: {} + index-to-position@1.2.0: {} + infima@0.2.0-alpha.45: {} inherits@2.0.4: {} @@ -10701,12 +10653,11 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@3.14.2: + js-yaml@4.3.2: dependencies: - argparse: 1.0.10 - esprima: 4.0.1 + argparse: 2.0.1 - js-yaml@4.2.0: + js-yaml@5.4.2: dependencies: argparse: 2.0.1 @@ -11349,7 +11300,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.13 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -11403,7 +11354,7 @@ snapshots: dependencies: schema-utils: 4.3.3 tapable: 2.3.3 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) minimalistic-assert@1.0.1: {} @@ -11425,6 +11376,14 @@ snapshots: optionalDependencies: react-dom: 19.2.7(react@19.2.7) + mobx-react@9.2.0(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + mobx: 6.16.1 + mobx-react-lite: 4.1.1(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + optionalDependencies: + react-dom: 19.2.7(react@19.2.7) + mobx-react@9.2.2(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: mobx: 6.16.1 @@ -11498,7 +11457,7 @@ snapshots: dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) oas-kit-common@1.0.8: dependencies: @@ -11577,6 +11536,16 @@ snapshots: fast-xml-parser: 5.9.0 json-pointer: 0.6.2 + openapi-typescript@7.13.0(typescript@5.9.3): + dependencies: + '@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: 5.9.3 + yargs-parser: 21.1.1 + opener@1.5.2: {} p-cancelable@3.0.0: {} @@ -11643,6 +11612,12 @@ 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 + parse-numeric-range@1.3.0: {} parse5-htmlparser2-tree-adapter@7.1.0: @@ -11856,7 +11831,7 @@ snapshots: jiti: 1.21.7 postcss: 8.5.15 semver: 7.8.4 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - typescript @@ -12249,7 +12224,7 @@ snapshots: dependencies: '@babel/runtime': 7.29.7 react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.7)' - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) react-router-config@5.1.1(react-router@5.3.4(react@19.2.7))(react@19.2.7): dependencies: @@ -12340,7 +12315,7 @@ snapshots: redoc@2.4.0(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): dependencies: - '@redocly/openapi-core': 1.16.0 + '@redocly/openapi-core': 1.34.20(supports-color@10.2.2) classnames: 2.5.1 core-js: 3.49.0 decko: 1.2.0 @@ -12371,12 +12346,45 @@ snapshots: - react-native - supports-color - redocusaurus@2.5.0(@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@docusaurus/utils@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): + redoc@2.5.4(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): + dependencies: + '@redocly/openapi-core': 1.34.20(supports-color@10.2.2) + classnames: 2.5.1 + core-js: 3.49.0 + decko: 1.2.0 + dompurify: 3.4.10 + eventemitter3: 5.0.4 + json-pointer: 0.6.2 + lunr: 2.3.9 + mark.js: 8.11.1 + marked: 4.3.0 + mobx: 6.16.1 + mobx-react: 9.2.0(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + openapi-sampler: 1.7.4 + path-browserify: 1.0.1 + perfect-scrollbar: 1.5.6 + polished: 4.3.1 + prismjs: 1.30.0 + prop-types: 15.8.1 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-tabs: 6.1.1(react@19.2.7) + slugify: 1.4.7 + stickyfill: 1.1.1 + styled-components: 6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + swagger2openapi: 7.0.8 + url-template: 2.0.8 + transitivePeerDependencies: + - encoding + - react-native + - supports-color + + redocusaurus@2.5.2(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@docusaurus/utils@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): dependencies: - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@docusaurus/utils': 3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - docusaurus-plugin-redoc: 2.5.0(@docusaurus/utils@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) - docusaurus-theme-redoc: 2.5.0(@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) + '@docusaurus/theme-common': 3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@docusaurus/utils': 3.10.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + docusaurus-plugin-redoc: 2.5.0(@docusaurus/utils@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(mobx@6.16.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(styled-components@6.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) + docusaurus-theme-redoc: 2.5.1(@docusaurus/theme-common@3.10.2(@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(postcss@8.5.15))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.11)(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@swc/core@1.15.41)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(core-js@3.49.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) transitivePeerDependencies: - core-js - css-to-react-native @@ -12789,7 +12797,7 @@ snapshots: spdy-transport@3.0.0: dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -12800,7 +12808,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -12808,8 +12816,6 @@ snapshots: transitivePeerDependencies: - supports-color - sprintf-js@1.0.3: {} - srcset@4.0.0: {} statuses@1.5.0: {} @@ -12896,6 +12902,8 @@ snapshots: stylis@4.3.6: {} + supports-color@10.2.2: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -12938,7 +12946,7 @@ snapshots: dependencies: '@swc/core': 1.15.41 '@swc/counter': 0.1.3 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) tapable@2.3.3: {} @@ -12948,7 +12956,7 @@ snapshots: jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.48.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) optionalDependencies: '@swc/core': 1.15.41 '@swc/html': 1.15.41 @@ -12961,7 +12969,7 @@ snapshots: jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.48.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) optionalDependencies: '@swc/core': 1.15.41 clean-css: 5.3.3 @@ -12969,17 +12977,6 @@ snapshots: html-minifier-terser: 7.2.0 postcss: 8.5.15 - terser-webpack-plugin@5.6.1(@swc/core@1.15.41)(postcss@8.5.15)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - terser: 5.48.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) - optionalDependencies: - '@swc/core': 1.15.41 - postcss: 8.5.15 - terser@5.48.0: dependencies: '@jridgewell/source-map': 0.3.11 @@ -13029,6 +13026,8 @@ snapshots: type-fest@2.19.0: {} + type-fest@4.41.0: {} + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -13123,6 +13122,8 @@ snapshots: semver-diff: 4.0.0 xdg-basedir: 5.1.0 + uri-js-replace@1.0.1: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -13132,7 +13133,7 @@ snapshots: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) optionalDependencies: file-loader: 6.2.0(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) @@ -13210,7 +13211,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - tslib @@ -13245,7 +13246,7 @@ snapshots: webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) ws: 8.21.0 optionalDependencies: - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) transitivePeerDependencies: - bufferutil - debug @@ -13345,45 +13346,6 @@ snapshots: - postcss - uglify-js - webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15): - dependencies: - '@types/estree': 1.0.9 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.17.0 - acorn-import-phases: 1.0.4(acorn@8.17.0) - browserslist: 4.28.2 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.24.0 - es-module-lexer: 2.1.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - loader-runner: 4.3.2 - mime-db: 1.54.0 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.3 - terser-webpack-plugin: 5.6.1(@swc/core@1.15.41)(postcss@8.5.15)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)) - watchpack: 2.5.2 - webpack-sources: 3.5.0 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - uglify-js - webpackbar@7.0.0(@rspack/core@1.7.11)(webpack@5.107.2(@swc/core@1.15.41)(postcss@8.5.15)): dependencies: ansis: 3.17.0 @@ -13392,7 +13354,7 @@ snapshots: std-env: 3.10.0 optionalDependencies: '@rspack/core': 1.7.11 - webpack: 5.107.2(@swc/core@1.15.41)(postcss@8.5.15) + webpack: 5.107.2(@swc/core@1.15.41)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.15))(html-minifier-terser@7.2.0)(postcss@8.5.15) websocket-driver@0.7.5: dependencies: diff --git a/website/pnpm-workspace.yaml b/website/pnpm-workspace.yaml index ad5f2453e..b033fc8b4 100644 --- a/website/pnpm-workspace.yaml +++ b/website/pnpm-workspace.yaml @@ -4,3 +4,7 @@ packages: allowBuilds: '@swc/core': true core-js: true + +# Redocusaurus pins an older renderer; use the current compatible ReDoc release. +overrides: + "docusaurus-theme-redoc>redoc": 2.5.4 diff --git a/website/scripts/check-openapi.mjs b/website/scripts/check-openapi.mjs new file mode 100644 index 000000000..06556739b --- /dev/null +++ b/website/scripts/check-openapi.mjs @@ -0,0 +1,200 @@ +import assert from "node:assert/strict"; +import { readFile, writeFile, mkdtemp, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { createRequire } from "node:module"; +import { execFileSync } from "node:child_process"; +import * as yaml from "js-yaml"; +import openapiTS, { astToString } from "openapi-typescript"; +import ts from "typescript"; + +const root = new URL("../", import.meta.url); +const contracts = []; +const presentationKeys = new Set([ + "description", + "summary", + "title", + "example", + "examples", + "externalDocs", + "x-codeSamples", +]); + +function contract(value, key) { + if (Array.isArray(value)) { + const items = value.map((item) => contract(item)); + return ["required", "enum", "type"].includes(key) ? items.sort() : items; + } + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value) + .filter(([name]) => !presentationKeys.has(name)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([name, nested]) => [name, contract(nested, name)]), + ); + } + return value; +} + +for (const filename of ["openapi_v2.yaml", "openapi_v2.en.yaml"]) { + // Match the generator parser so unquoted numeric SAT codes fail validation. + const spec = yaml.load(await readFile(new URL(filename, root), "utf8")); + function walk(value, path = []) { + if (!value || typeof value !== "object") return; + assert( + !("nullable" in value), + `Use OpenAPI 3.1 null unions: ${path.join(".")}`, + ); + if ( + ((path[0] === "components" && path[1] === "schemas") || + path.includes("schema")) && + (typeof value.type === "string" || Array.isArray(value.type)) + ) { + for (const type of Array.isArray(value.type) ? value.type : [value.type]) + assert( + [ + "null", "boolean", "object", "array", "number", "string", "integer", + ].includes(type), + `Invalid schema type: ${path.join(".")}`, + ); + } + if (value.type === "string") { + for (const item of value.enum || []) + assert.equal( + typeof item, + "string", + `String enum values must be quoted when needed: ${path.join(".")}`, + ); + for (const key of ["example", "default", "const"]) + if (key in value) + assert.equal( + typeof value[key], + "string", + `String ${key} must remain a string: ${path.join(".")}`, + ); + } + if (value.$ref?.startsWith("#/")) { + let target = spec; + for (const part of value.$ref.slice(2).split("/")) { + target = target?.[part.replace(/~1/g, "/").replace(/~0/g, "~")]; + } + assert(target, `Unresolved reference: ${value.$ref}`); + } + for (const [key, child] of Object.entries(value)) + if (!presentationKeys.has(key) && !["default", "enum", "const"].includes(key)) + walk(child, [...path, key]); + } + walk(spec); + assert.equal( + spec.components.schemas.SignedDownloadUrl.properties.url.format, + "uri", + "Download links must be declared as URI strings", + ); + for (const invoiceType of spec.components.schemas.InvoiceCreateInput.oneOf) { + assert.equal(invoiceType.oneOf.length, 2, "Expected emission and draft variants"); + assert.deepEqual( + invoiceType.oneOf.map((variant) => variant.allOf.at(-1).properties.status.const), + ["pending", "draft"], + "Invoice display variants must match their contractual status", + ); + } + const ids = new Set(); + for (const items of [spec.paths, spec.webhooks || {}]) { + for (const [path, item] of Object.entries(items)) { + for (const [method, operation] of Object.entries(item)) { + if (!operation.responses) continue; + assert(operation.operationId, `Missing operationId: ${method} ${path}`); + assert( + !ids.has(operation.operationId), + `Duplicate operationId: ${operation.operationId}`, + ); + ids.add(operation.operationId); + for (const sample of operation["x-codeSamples"] || []) { + if (!["JavaScript", "TypeScript"].includes(sample.lang)) continue; + const result = ts.transpileModule(sample.source, { + compilerOptions: { + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.ESNext, + }, + fileName: sample.lang === "JavaScript" ? "sample.js" : "sample.ts", + reportDiagnostics: true, + }); + assert.equal( + result.diagnostics.length, + 0, + `Invalid ${sample.lang} sample: ${operation.operationId}`, + ); + } + + const params = [ + ...(item.parameters || []), + ...(operation.parameters || []), + ].map((parameter) => + parameter.$ref + ? spec.components.parameters[parameter.$ref.split("/").at(-1)] + : parameter, + ); + for (const match of path.matchAll(/\{([^}]+)\}/g)) { + assert( + params.some( + (parameter) => + parameter.in === "path" && + parameter.name === match[1] && + parameter.required === true, + ), + `Missing required path parameter: ${path}`, + ); + } + } + } + } + contracts.push( + contract({ + paths: spec.paths, + webhooks: spec.webhooks, + components: spec.components, + }), + ); + const directory = await mkdtemp(join(tmpdir(), "facturapi-openapi-")); + try { + await writeFile( + join(directory, "schema.d.ts"), + astToString( + await openapiTS(new URL(filename, root), { + defaultNonNullable: false, + emptyObjectsUnknown: true, + }), + ), + ); + await writeFile( + join(directory, "fixture.ts"), + await readFile(new URL("test/openapi-types.fixture.txt", root)), + ); + execFileSync( + process.execPath, + [ + createRequire(import.meta.url).resolve("typescript/bin/tsc"), + "--noEmit", + "--strict", + "--skipLibCheck", + "--target", + "ES2022", + "--moduleResolution", + "node", + join(directory, "fixture.ts"), + ], + { stdio: "inherit" }, + ); + } finally { + await rm(directory, { recursive: true, force: true }); + } + console.log( + `${filename}: ${ids.size} operations, references and generated type contracts verified`, + ); +} +assert.deepEqual( + contracts[0], + contracts[1], + "Spanish and English must describe the same API contract", +); +console.log("Locale contracts match"); diff --git a/website/src/css/custom.css b/website/src/css/custom.css index c849a4172..4d0ff1ea8 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -390,6 +390,55 @@ body[data-scrolled='true'] .navbar { display: none !important; } +/* Keep invoice mode and related fields together when requirements change. */ +[id='operation/createInvoice'] tbody:has(> tr > td[title='status'] + td select) { + display: grid; + grid-template-columns: max-content minmax(0, 1fr); + + > tr { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + } + + > tr > td { + width: auto; + } + + > tr > td[colspan] { + grid-column: 1 / -1; + } + + > tr:has(> td[title='status']) { + order: -11; + + > td + td > div { + display: flex; + flex-direction: column; + + > div:has(> select) { + order: -1; + margin-bottom: 0.5rem; + } + } + } + + > tr:has(> td[title='type']) { order: -10; } + > tr:has(> td[title='customer']) { order: -9; } + > tr:has(> td[title='third_party']) { order: -8; } + > tr:has(> td:is([title='items'], [title='complements'])) { order: -7; } + > tr:has(> td[title='use']) { order: -6; } + > tr:has(> td:is([title='payment_form'], [title='payment_method'], [title='conditions'])) { order: -5; } + > tr:has(> td:is([title='currency'], [title='exchange'])) { order: -4; } + > tr:has(> td:is([title='date'], [title='folio_number'], [title='series'])) { order: -3; } + > tr:has(> td:is([title='related_documents'], [title='global'], [title='export'])) { order: 1; } + > tr:has(> td:is([title='pdf_custom_section'], [title='addenda'], [title='namespaces'], [title='pdf_options'])) { order: 2; } + + @media (max-width: 50rem) { + grid-template-columns: minmax(0, 1fr); + } +} + html[data-theme='dark'] .redocusaurus button[aria-expanded='true'] { border-color: transparent !important; } diff --git a/website/src/pages/api.tsx b/website/src/pages/api.tsx index 26712324c..a5c9eec96 100644 --- a/website/src/pages/api.tsx +++ b/website/src/pages/api.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import ApiDoc from '@theme/ApiDoc'; import useSpecData from '@theme/useSpecData'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; @@ -8,6 +8,29 @@ function CustomPage() { const {i18n} = useDocusaurusContext(); const locale = i18n.currentLocale; const specData = useSpecData(`api-${locale}`); + const displaySpecData = useMemo(() => { + const spec = structuredClone(specData.spec); + // ReDoc needs named discriminator variants to render a status selector. + // Keep this presentation hint out of the contract: status may be omitted. + spec.components.schemas.InvoiceCreateInput.oneOf = + spec.components.schemas.InvoiceCreateInput.oneOf.map( + (invoiceType: {oneOf: {allOf: {properties: {status: {const: string}}}[]}[]}, typeIndex: number) => { + const mapping: Record = {}; + return { + ...invoiceType, + oneOf: invoiceType.oneOf.map((variant) => { + const status = variant.allOf.at(-1)!.properties.status.const; + const name = `InvoiceCreateDisplay${typeIndex}${status}`; + spec.components.schemas[name] = variant; + mapping[status] = `#/components/schemas/${name}`; + return {$ref: mapping[status]}; + }), + discriminator: {propertyName: 'status', mapping}, + }; + }, + ); + return {...specData, spec}; + }, [specData]); return ( ); } -export default CustomPage; \ No newline at end of file +export default CustomPage; diff --git a/website/test/openapi-types.fixture.txt b/website/test/openapi-types.fixture.txt new file mode 100644 index 000000000..427bc6d87 --- /dev/null +++ b/website/test/openapi-types.fixture.txt @@ -0,0 +1,220 @@ +import type { components, operations, webhooks } from "./schema"; +const invoice: components["schemas"]["InvoiceCreateInput"] = { + customer: "cus_example", + items: [ + { + quantity: 1, + product: { + description: "Ukelele", + product_key: "60131324", + price: 345.6, + }, + }, + ], + payment_form: "28", + use: "G01", +}; +const draft: components["schemas"]["InvoiceCreateInput"] = { status: "draft" }; +const receiptEvent: components["schemas"]["ApiEvent"] = { + id: "evt", + created_at: "2026-09-29T00:00:00Z", + livemode: false, + organization: "org", + type: "receipt.status_updated", + related_resource_messages: [], + data: { + type: "receipt", + object: { + id: "rec", created_at: "2026-09-29T00:00:00Z", livemode: false, + date: "2026-09-29T00:00:00Z", expires_at: "2026-10-01T00:00:00Z", + }, + }, +}; +const validation: operations["validateWebhookSignature"]["requestBody"]["content"]["application/json"] = + { + secret: "secret", + signature: "123", + payload: '{"type":"receipt.status_updated"}', + }; +const nullDate: components["schemas"]["InvoiceProperties"]["date"] = null; +const draftStamp: components["schemas"]["InvoiceDraftProperties"]["stamp"] = null; +const draftUuid: components["schemas"]["InvoiceDraftProperties"]["uuid"] = null; +const missingDraftUuid: components["schemas"]["InvoiceDraftProperties"]["uuid"] = undefined; +const paymentTaxability: NonNullable< + components["schemas"]["PaymentInput"]["related_documents"] +>[number]["taxability"] = "01"; +// @ts-expect-error SAT codes retain their leading zero +const invalidPaymentTaxability: typeof paymentTaxability = "1"; +// @ts-expect-error taxability only accepts the documented SAT codes +const unknownPaymentTaxability: typeof paymentTaxability = "09"; +const certificate: NonNullable = { + has_certificate: false, +}; +const missingCertificateDate: typeof certificate.updated_at = undefined; +// @ts-expect-error absent certificate dates are omitted, not null +const nullCertificateDate: typeof certificate.updated_at = null; +const fiel: NonNullable = { + has_certificate: false, +}; +const missingFielDate: typeof fiel.expires_at = undefined; +// @ts-expect-error absent FIEL dates are omitted, not null +const nullFielDate: typeof fiel.expires_at = null; +const callback: keyof webhooks = "customer.edit_link_completed"; +const retainedTax: NonNullable< + NonNullable["imp_retenidos"] +>[number]["tipo_pago_ret"] = "01"; +// @ts-expect-error SAT codes retain their leading zero +const invalidRetainedTax: typeof retainedTax = "1"; +// @ts-expect-error event discriminants must correlate with the resource +const invalid: components["schemas"]["ApiEvent"] = { + ...receiptEvent, + data: { + type: "invoice", + object: { + id: "invoice", + created_at: "2026-09-29T00:00:00Z", + livemode: false, + date: null, + }, + }, +}; +const pago: components["schemas"]["PagoOrCustomComplementInput"] = { + type: "pago", + data: [{ payment_form: "28", related_documents: [{ + uuid: "39c85a3f-275b-4341-b259-e8971d9f8a94", installment: 1, + last_balance: 100, amount: 100, taxes: [], taxability: "01", + }] }], +}; +const pagoResponse: components["schemas"]["InvoiceComplementProperties"] = { + type: "pago", data: [{ date: "2026-09-29T00:00:00Z", payment_form: "28", related_documents: [] }], +}; +// @ts-expect-error a payment complement requires payment data, not payroll data +const wrongPago: components["schemas"]["PagoOrCustomComplementInput"] = { type: "pago", data: { tipo_nomina: "O" } }; +const customResponse: components["schemas"]["InvoiceComplementProperties"] = { type: "custom", data: "" }; +void [pago, pagoResponse, wrongPago, customResponse]; +void [invoice, draft, receiptEvent, validation, nullDate, draftStamp, draftUuid, missingDraftUuid, paymentTaxability, invalidPaymentTaxability, unknownPaymentTaxability, certificate, missingCertificateDate, nullCertificateDate, fiel, missingFielDate, nullFielDate, callback, retainedTax, invalidRetainedTax, invalid]; + +const nominaEdit: components["schemas"]["InvoiceNominaEditInput"] = { type: "N" }; +// @ts-expect-error payroll editing has its own CFDI discriminator +const wrongNominaEdit: components["schemas"]["InvoiceNominaEditInput"] = { type: "P" }; +const paymentEdit: components["schemas"]["InvoicePagoEditInput"] = { type: "P", complements: [pago] }; +// @ts-expect-error payment editing has its own CFDI discriminator +const wrongPaymentEdit: components["schemas"]["InvoicePagoEditInput"] = { type: "N" }; +const legendsDraft: components["schemas"]["InvoiceCreateInput"] = { status: "draft", complements: [{ type: "leyendas_fiscales", data: { leyendas: [{ texto_leyenda: "Ejemplo" }] } }] }; +const plainPerception: components["schemas"]["NominaPercepcionInput"] = { tipo_percepcion: "001", clave: "ABC", importe_gravado: 1, importe_exento: 0 }; +const overtimePerception: components["schemas"]["NominaPercepcionInput"] = { ...plainPerception, tipo_percepcion: "019", horas_extra: [{ dias: 1, tipo_horas: "01", horas_extra: 1, importe_pagado: 1 }] }; +// @ts-expect-error overtime perception requires its hours-extra structure +const missingHours: components["schemas"]["NominaPercepcionInput"] = { tipo_percepcion: "019", clave: "ABC", importe_gravado: 1, importe_exento: 0 }; +const mixedFunds: components["schemas"]["NominaEntidadSncfInput"] = { origen_recurso: "IM", monto_recurso_propio: 1 }; +const federalFunds: components["schemas"]["NominaEntidadSncfInput"] = { origen_recurso: "IF" }; +// @ts-expect-error mixed funding requires its own-resource amount +const missingOwnFunds: components["schemas"]["NominaEntidadSncfInput"] = { origen_recurso: "IM" }; +const ieps: components["schemas"]["BaseTax"] = { type: "IEPS", rate: 0.08, ieps_mode: "unit" }; +// @ts-expect-error an explicitly IEPS schema cannot identify an IVA tax +const wrongIeps: components["schemas"]["IepsTax"] = { type: "IVA", rate: 0.16 }; +// @ts-expect-error selecting road transport requires its vehicle and insurance data +const incompleteRoad: components["schemas"]["CartaPorteAutotransporte"] = { PermSCT: "TPAF01", NumPermisoSCT: "Example" }; +void [nominaEdit, wrongNominaEdit, paymentEdit, wrongPaymentEdit, legendsDraft, plainPerception, overtimePerception, missingHours, mixedFunds, federalFunds, missingOwnFunds, ieps, wrongIeps, incompleteRoad]; +// @ts-expect-error composed perception input must retain its required amounts +const missingPerceptionAmounts: components["schemas"]["NominaPercepcionInput"] = { tipo_percepcion: "001", clave: "ABC" }; +// @ts-expect-error composed hours-extra input must retain its required payment amount +const missingOvertimeAmount: components["schemas"]["NominaHorasExtraInput"] = { dias: 1, tipo_horas: "01", horas_extra: 1 }; +const publicAidPerception: components["schemas"]["NominaPercepcionInput"] = { ...plainPerception, tipo_percepcion: "056" }; +const customPayroll: components["schemas"]["NominaOtroPagoInput"] = { tipo_otro_pago: "002", clave: "ABC", importe: 1 }; +void [missingPerceptionAmounts, missingOvertimeAmount, publicAidPerception, customPayroll]; +const incomeWithDefaultUse: components["schemas"]["InvoiceCreateInput"] = { customer: "cus", payment_form: "28", items: [{ quantity: 1, product: { description: "Ejemplo", product_key: "60131324", price: 1 } }] }; +const incomeWithNullUse: components["schemas"]["InvoiceCreateInput"] = { ...incomeWithDefaultUse, use: null }; +const clearedDraft: components["schemas"]["InvoiceCreateInput"] = { status: "draft", customer: null, payment_form: null, use: null }; +const clearedCreditDraft: components["schemas"]["InvoiceEgresoEditInput"] = { type: "E", customer: null }; +const clearedPaymentDraft: components["schemas"]["InvoicePagoEditInput"] = { type: "P", customer: null }; +// @ts-expect-error a payroll customer can be omitted, but cannot be cleared with null +const nullPayrollCustomer: components["schemas"]["InvoiceNominaEditInput"] = { type: "N", customer: null }; +// @ts-expect-error a transfer customer can be omitted, but cannot be cleared with null +const nullTransferCustomer: components["schemas"]["InvoiceTrasladoEditInput"] = { type: "T", customer: null }; +const singlePayment: components["schemas"]["PagoComplementInput"] = { type: "pago", data: { payment_form: "28", related_documents: [{ uuid: "39c85a3f-275b-4341-b259-e8971d9f8a94", installment: 1, last_balance: 1, amount: 1, taxes: [] }] } }; +// @ts-expect-error issued invoices still require a real customer +const nullIssuedCustomer: components["schemas"]["InvoiceCreateInput"] = { customer: null, payment_form: "28", items: incomeWithDefaultUse.items }; +// @ts-expect-error a draft edit cannot request the pending status +const pendingDraftEdit: components["schemas"]["InvoiceEgresoEditInput"] = { type: "E", status: "pending" }; +void [incomeWithDefaultUse, incomeWithNullUse, clearedDraft, clearedCreditDraft, clearedPaymentDraft, nullPayrollCustomer, nullTransferCustomer, singlePayment, nullIssuedCustomer, pendingDraftEdit]; + +const draftWithoutCustomer: components["schemas"]["InvoiceDraftProperties"]["customer"] = null; +const existingWildcard: NonNullable[number] = "*"; +// @ts-expect-error webhook creation requires explicit event names +const wildcardCreate: components["schemas"]["WebhookCreateInput"] = { url: "https://example.com/hooks", enabled_events: ["*"] }; +// @ts-expect-error webhook editing requires explicit event names +const wildcardEdit: components["schemas"]["WebhookCreateEdit"] = { status: "enabled", enabled_events: ["*"] }; +void [draftWithoutCustomer, existingWildcard, wildcardCreate, wildcardEdit]; + +// Creation can return an issued invoice or a draft, with typed common fields. +declare const createdInvoiceResponse: operations["createInvoice"]["responses"][200]["content"]["application/json"]; +const createdInvoiceDate: string | null | undefined = createdInvoiceResponse.date; +const createdInvoiceStamp: components["schemas"]["Stamp"] | null | undefined = createdInvoiceResponse.stamp; +void createdInvoiceDate; +void createdInvoiceStamp; + +// A payment summary can be reused directly in a payment complement. +declare const paymentSummary: operations["getInvoicePaymentSummary"]["responses"][200]["content"]["application/json"]; +const summaryRelatedDocument: components["schemas"]["PaymentInput"]["related_documents"][number] = paymentSummary; +// Catalog codes are strings: their leading zeros are part of their identity. +// @ts-expect-error a numeric catalog code is not a valid string code +const numericPaymentTaxability: typeof paymentTaxability = 1; +void [summaryRelatedDocument, numericPaymentTaxability]; + +// Customer creation requirements depend on country and generic RFCs. +const nationalCustomer: components['schemas']['CustomerCreateInput'] = { + legal_name: 'Cliente nacional', tax_id: 'ABC101010111', tax_system: '601', address: { zip: '83200' }, +}; +const foreignCustomer: components['schemas']['CustomerCreateInput'] = { + legal_name: 'Foreign customer', address: { country: 'USA' }, +}; +const genericCustomer: components['schemas']['CustomerCreateInput'] = { + legal_name: 'PUBLICO EN GENERAL', tax_id: 'XAXX010101000', +}; +// @ts-expect-error country is needed to select foreign rules +const foreignWithoutCountry: components['schemas']['CustomerCreateInput'] = { legal_name: 'Foreign customer', address: {} }; +// @ts-expect-error national customers require an RFC +const nationalWithoutRfc: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_system: '601', address: { zip: '83200' } }; +// @ts-expect-error national customers require a tax regime +const nationalWithoutRegime: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_id: 'ABC101010111', address: { zip: '83200' } }; +// @ts-expect-error explicit national address needs a postal code +const nationalWithoutZip: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_id: 'ABC101010111', tax_system: '601', address: {} }; +// @ts-expect-error foreign customers use the regime 616 +const foreignWithWrongRegime: components['schemas']['CustomerForeignCreateInput'] = { legal_name: 'Foreign', tax_system: '601', address: { country: 'USA' } }; +// @ts-expect-error generic RFCs use 616 +const genericWithWrongRegime: components['schemas']['CustomerGenericCreateInput'] = { legal_name: 'Cliente', tax_id: 'XAXX010101000', tax_system: '601' }; +const defaultGlobal: components['schemas']['GlobalInvoiceInput'] = {}; +const explicitGlobal: components['schemas']['GlobalInvoiceInput'] = { receipts: ['rec_ejemplo'], from: '2026-01-01', to: '2026-01-31' }; +// @ts-expect-error explicit receipts require both dates +const explicitGlobalWithoutDates: components['schemas']['GlobalInvoiceInput'] = { receipts: ['rec_ejemplo'] }; +const cancelReplacement: components['schemas']['CancellationQueryInput'] = { motive: '04', substitution: 'inv_ejemplo' }; +const cancelWithoutReplacement: components['schemas']['CancellationQueryInput'] = { motive: '02' }; +const deleteDraft: components['schemas']['CancellationQueryInput'] = {}; +// @ts-expect-error replacement motives require the substitution +const cancelMissingReplacement: components['schemas']['CancellationQueryInput'] = { motive: '01' }; +// @ts-expect-error a replacement without a motive is not a cancellation request +const cancelMissingMotive: components['schemas']['CancellationQueryInput'] = { substitution: 'inv_ejemplo' }; +void [nationalCustomer, foreignCustomer, genericCustomer, foreignWithoutCountry, nationalWithoutRfc, nationalWithoutRegime, nationalWithoutZip, foreignWithWrongRegime, genericWithWrongRegime, defaultGlobal, explicitGlobal, explicitGlobalWithoutDates, cancelReplacement, cancelWithoutReplacement, deleteDraft, cancelMissingReplacement, cancelMissingMotive]; +// Required fields cannot be supplied as undefined. +// @ts-expect-error undefined fiscal name is not a customer name +const undefinedCustomerName: components['schemas']['CustomerCreateInput'] = { legal_name: undefined, address: { country: 'USA' } }; +// @ts-expect-error undefined tax regime does not complete a national customer +const undefinedNationalRegime: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_id: 'ABC101010111', tax_system: undefined, address: { zip: '83200' } }; +// @ts-expect-error undefined zip does not complete a national address +const undefinedNationalZip: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_id: 'ABC101010111', tax_system: '601', address: { zip: undefined } }; +// @ts-expect-error explicit receipt selection needs actual dates +const undefinedGlobalDates: components['schemas']['GlobalInvoiceInput'] = { receipts: ['rec_ejemplo'], from: undefined, to: undefined }; +void [undefinedCustomerName, undefinedNationalRegime, undefinedNationalZip, undefinedGlobalDates]; +// Incomplete and foreign customer responses may have null fiscal fields. +declare const incompleteCustomerResponse: components['schemas']['Customer']; +const responseTaxId: string | null | undefined = incompleteCustomerResponse.tax_id; +const responseTaxSystem: string | null | undefined = incompleteCustomerResponse.tax_system; +const incompleteCustomerWithEmptyRfc: components['schemas']['CustomerCreateWithEditLinkInput'] = { tax_id: null }; +// @ts-expect-error edit-link creation still validates a supplied fiscal regime +const incompleteCustomerWithNullRegime: components['schemas']['CustomerCreateWithEditLinkInput'] = { tax_system: null }; +// @ts-expect-error national customer creation requires a non-null fiscal regime +const nationalCustomerWithNullRegime: components['schemas']['CustomerNationalCreateInput'] = { legal_name: 'Cliente', tax_id: 'ABC101010111', tax_system: null, address: { zip: '83200' } }; +void [responseTaxId, responseTaxSystem, incompleteCustomerWithEmptyRfc, incompleteCustomerWithNullRegime, nationalCustomerWithNullRegime]; +const expiredCustomerEditLink: components['schemas']['CustomerNonEditableProperties'] = { edit_link: null, edit_link_expires_at: null }; +const clearedCustomerPhone: components['schemas']['CustomerProperties'] = { phone: null }; +void [expiredCustomerEditLink, clearedCustomerPhone]; diff --git a/website/tsconfig.json b/website/tsconfig.json index 314eab8a4..4dbcfa4ce 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -1,6 +1,7 @@ { // This file is not used in compilation. It is here just for a nice editor experience. "extends": "@docusaurus/tsconfig", + "exclude": ["node_modules", "build", ".docusaurus"], "compilerOptions": { "baseUrl": "." }