> ## Documentation Index
> Fetch the complete documentation index at: https://www.finseed.es/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate an invoice payload

> Dry-runs an invoice creation payload through the exact validations the create endpoint applies, including the just-in-time census check of the recipient tax id, without persisting anything. Failures return the same errors the create endpoint would; success returns the totals the invoice would carry. A passing validation does not reserve an invoice number and cannot fully guarantee the subsequent creation.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/invoices/validate
openapi: 3.1.0
info:
  title: Finseed API
  version: 1.0.0
  description: >-
    REST API for programmatic Verifactu invoicing. Every request is sent over
    HTTPS and authenticated with an API key passed as a bearer token. Each key
    is scoped to a single environment (test or live). Payloads are JSON with
    snake_case fields: amounts are integer minor units (cents) and timestamps
    are RFC 3339 in UTC. List endpoints are cursor-paginated. Errors return a
    small application/json envelope with a stable, machine-readable `code`.
servers:
  - url: https://api.finseed.es
security:
  - bearerAuth: []
paths:
  /v1/invoices/validate:
    post:
      tags:
        - Invoices
      summary: Validate an invoice payload
      description: >-
        Dry-runs an invoice creation payload through the exact validations the
        create endpoint applies, including the just-in-time census check of the
        recipient tax id, without persisting anything. Failures return the same
        errors the create endpoint would; success returns the totals the invoice
        would carry. A passing validation does not reserve an invoice number and
        cannot fully guarantee the subsequent creation.
      operationId: validateInvoice
      requestBody:
        description: The invoice payload to validate.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InvoiceCreateRequest'
      responses:
        '200':
          description: The payload is valid, with the totals it would carry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceValidateResult'
        '400':
          description: >-
            The request was rejected during validation. The `errors` array lists
            each failing field with a reason, so you can map the failure back to
            a specific parameter.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: invalid_request
                detail: >-
                  The request is not valid. A parameter is missing, malformed,
                  or out of range. See the `errors` array for the fields that
                  failed.
                errors: []
                doc_url: >-
                  https://www.finseed.es/docs/api-reference/errors#invalid_request
        '401':
          description: >-
            Authentication failed: the API key is missing, malformed, or
            revoked. Send a valid key as a bearer token in the `Authorization`
            header. Each key is bound to a single environment (test or live).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: unauthorized
                detail: >-
                  Authentication failed. Send your API key as a bearer token in
                  the `Authorization` header. Keys are scoped to one
                  environment, so a test key cannot read live data and vice
                  versa.
                errors: []
                doc_url: https://www.finseed.es/docs/api-reference/errors#unauthorized
        '402':
          description: >-
            Live invoice issuance requires an active subscription. When the
            account has no active plan, live keys receive this error until a
            subscription is in place. Test-environment keys are unaffected.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: no_active_subscription
                detail: >-
                  This account cannot create invoices without an active
                  subscription. Check your plan to continue issuing invoices.
                errors: []
                doc_url: >-
                  https://www.finseed.es/docs/api-reference/errors#no_active_subscription
        '403':
          description: >-
            Live invoice issuance requires the company's AEAT representation
            mandate to be approved, which happens during onboarding. Until then,
            live keys receive this error; test-environment keys can issue freely
            (test invoices are never sent to AEAT).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: aeat_mandate_not_approved
                detail: >-
                  This account cannot issue live invoices yet: the AEAT
                  representation mandate is pending approval. Complete the
                  onboarding in the dashboard, or use a test-environment key
                  meanwhile.
                errors: []
                doc_url: >-
                  https://www.finseed.es/docs/api-reference/errors#aeat_mandate_not_approved
        '422':
          description: >-
            Returned as `external_reference_invalid`: The external original
            reference is malformed: the `number` exceeds 60 characters or
            contains forbidden characters (`"`, `'`, `<`, `>`, `=`), or
            `issued_on` is not a valid calendar date.


            Returned as `external_reference_matches_existing_invoice`: The
            external number matches an invoice that was actually issued through
            Finseed. Rectify it as a local invoice with `rectifies.invoice_id`;
            `rectifies.external` is only for originals that never existed in
            Finseed.


            Returned as `family_balance_below_zero`: A rectificativa por
            diferencias adjusts the original by a delta. This delta would make
            the accumulated total of the correction chain negative, which is not
            a valid invoice. Reduce the delta.


            Returned as `insufficient_recipient_data`: The recipient block does
            not meet the legal minimums for a complete invoice (for example a
            too-short name or tax id, or an unrecognized country code). Fix the
            flagged recipient fields or issue a simplified invoice when no
            identified recipient exists.


            Returned as `invalid_number_series`: The `number_series_id` in the
            request body cannot be used to issue this invoice: it is malformed,
            belongs to another environment, or names a rectifying series
            (reserved for corrective invoices). List the usable series with the
            Number Series endpoints.


            Returned as `invalid_recargo_equivalencia`: The
            `recargo_equivalencia` flag requires every line to carry exactly one
            `vat` tax whose rate has a legal surcharge pairing (21%→5.2%,
            10%→1.4%, 4%→0.5%). Lines with other tax types or unpaired VAT rates
            cannot be invoiced under this regime.


            Returned as `invalid_rectifies_reference`: The `rectifies` block did
            not name exactly one original to correct. Supply either `invoice_id`
            for an invoice issued through Finseed, or `external` for one issued
            elsewhere — not both, and not neither.


            Returned as `invalid_tax_data`: The combination of tax types, rates
            and computed amounts is one the tax agency rejects (for example a
            positive rate that yields a zero tax amount on a non-zero line).
            Review the tax on each line.


            Returned as `invalid_tax_id`: The recipient tax id failed
            just-in-time validation. Either the format is invalid for its type,
            or the census lookup (AEAT for Spanish NIFs, VIES for EU VAT
            numbers) did not recognize the id together with the supplied name.
            Verify the id and use the exact name the recipient is registered
            under.


            Returned as `invalid_tax_rate`: A line item carries a tax rate the
            tax agency (AEAT) would reject for that tax type on the current
            date, a rate on a rate-free type, or a missing rate on a rated type.
            Spanish VAT (`vat`) currently accepts 0, 4, 10 and 21 percent for
            invoices issued today; historical temporary rates (2, 5, 7.5) only
            applied to past operation windows.


            Returned as `invoice_already_replaced`: The referenced invoice has
            already been fully replaced by a rectificativa por sustitución. Only
            the active head of the correction chain can be rectified; rectify
            the replacement instead.


            Returned as `invoice_already_voided`: The referenced invoice was
            voided (anulada). A voided invoice is legally cancelled, so it
            cannot be corrected with a rectificativa.


            Returned as `invoice_not_family_tip`: The referenced invoice is not
            the active head of its correction chain: a later rectificativa
            already corrects it. Rectify the current head of the chain instead.


            Returned as `invoice_not_rectifiable_at_aeat`: The referenced
            invoice is not in a state the tax agency (AEAT) allows a
            rectificativa against: its registration failed, was skipped, or
            never happened. Only invoices that registered successfully can be
            rectified.


            Returned as `invoice_pending_at_aeat`: The referenced invoice has
            not finished registering at the tax agency (AEAT). Poll it until
            `verifactu.status` leaves `pending`, then rectify it.


            Returned as `line_item_without_tax_items`: A rectificativa line item
            was submitted without a tax. Every line must declare its tax so the
            corrective document reconciles with the tax agency.


            Returned as `reason_incompatible_with_recipient`: The chosen
            `reason` restricts which recipient tax id types are allowed.
            `insolvency` accepts a Spanish NIF, an EU VAT number, or an
            unregistered recipient; `uncollectible` accepts a Spanish NIF or an
            unregistered recipient. The recipient on this invoice does not meet
            that restriction.


            Returned as `recipient_overrides_not_allowed_for_differences`: A
            rectificativa por diferencias inherits its recipient from the
            corrected invoice, so a `recipient` block cannot be supplied. Omit
            it, or issue a rectificativa por sustitución (`method:
            "substitution"`) when the recipient must change.


            Returned as `rectified_amounts_required_for_substitution`: When
            replacing an external original by substitution, the tax agency
            requires the original amounts (`ImporteRectificación`), which
            Finseed cannot compute because the original never existed here.
            Supply `rectifies.external.rectified_amounts`.


            Returned as `rectified_invoice_not_found`: The
            `rectifies.invoice_id` does not match any invoice in the environment
            the API key belongs to. Use the opaque `inv_` identifier of an
            invoice issued through Finseed; to correct an invoice issued
            elsewhere, use `rectifies.external` instead.


            Returned as `rectifying_series_invalid`: A rectificativa must be
            issued on a rectifying series. The `number_series_id` is malformed,
            belongs to another environment, or names a standard series. List
            your rectifying series with the Number Series endpoints, or omit it
            to use the environment default.


            Returned as `replacement_total_negative`: A rectificativa por
            sustitución restates the full invoice, so its net total cannot be
            negative. Adjust the line items so the total is at or above zero.


            Returned as `simplified_amount_exceeded`: Spanish law caps
            simplified invoices at 3,000 EUR including tax. Above that amount
            the recipient must be identified: send `type: "complete"` with a
            full recipient block.


            Returned as `simplified_incompatible_tax_type`: The invoice combines
            `type: "simplified"` with a tax type that legally requires an
            identified recipient, such as `es_inversion_sujeto_pasivo` (reverse
            charge). Issue a complete invoice for these operations.


            Returned as `tax_id_type_country_mismatch`: The supplied
            `tax_id_type` and `tax_id_country` contradict each other. Each type
            constrains the country: `es_nif` and `not_registered` require `ES`;
            `eu_vat` requires an EU country other than `ES`;
            `official_document`, `residence_certificate` and `other` require a
            country other than `ES`; `passport` accepts any country. Fix the
            pair, or omit `tax_id_country` when the type implies it (or omit
            both to auto-detect them from the tax id).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                external_reference_invalid:
                  summary: external_reference_invalid
                  value:
                    code: external_reference_invalid
                    detail: >-
                      The `rectifies.external` reference is invalid: the number
                      is too long or contains forbidden characters, or the issue
                      date is not a real date.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#external_reference_invalid
                external_reference_matches_existing_invoice:
                  summary: external_reference_matches_existing_invoice
                  value:
                    code: external_reference_matches_existing_invoice
                    detail: >-
                      The `rectifies.external.number` matches an invoice issued
                      through Finseed in this environment. Reference it with
                      `invoice_id` instead of `external`.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#external_reference_matches_existing_invoice
                family_balance_below_zero:
                  summary: family_balance_below_zero
                  value:
                    code: family_balance_below_zero
                    detail: >-
                      This rectificativa por diferencias would drive the
                      corrected invoice below zero across its whole correction
                      chain. Reduce the delta so the accumulated total stays at
                      or above zero.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#family_balance_below_zero
                insufficient_recipient_data:
                  summary: insufficient_recipient_data
                  value:
                    code: insufficient_recipient_data
                    detail: >-
                      The recipient data is not sufficient for a complete
                      invoice: a required field is missing or too short (name
                      and tax id have legal minimum lengths, and the country
                      must be a valid ISO code).
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#insufficient_recipient_data
                invalid_number_series:
                  summary: invalid_number_series
                  value:
                    code: invalid_number_series
                    detail: >-
                      The number_series_id does not name a usable series: it is
                      malformed, does not exist in this environment, or is a
                      rectifying series. Invoices are issued on standard series;
                      list yours with GET /v1/number_series.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_number_series
                invalid_recargo_equivalencia:
                  summary: invalid_recargo_equivalencia
                  value:
                    code: invalid_recargo_equivalencia
                    detail: >-
                      recargo_equivalencia could not be applied: every line must
                      carry exactly one VAT tax with a rate that has a legal
                      surcharge pairing (21, 10 or 4 percent).
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_recargo_equivalencia
                invalid_rectifies_reference:
                  summary: invalid_rectifies_reference
                  value:
                    code: invalid_rectifies_reference
                    detail: >-
                      The `rectifies` block must reference exactly one original:
                      either `invoice_id` (an invoice issued through Finseed) or
                      `external` (an invoice issued elsewhere), never both and
                      never neither.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_rectifies_reference
                invalid_tax_data:
                  summary: invalid_tax_data
                  value:
                    code: invalid_tax_data
                    detail: >-
                      The tax data on the invoice is inconsistent and the tax
                      agency would reject it. Review each line: the rate, the
                      amounts and the tax type must agree.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_tax_data
                invalid_tax_id:
                  summary: invalid_tax_id
                  value:
                    code: invalid_tax_id
                    detail: >-
                      The recipient tax id failed validation: its format is
                      invalid, or the id and name do not match the tax census
                      (AEAT for Spanish NIF, VIES for EU VAT numbers). Check the
                      id and the exact registered name.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_tax_id
                invalid_tax_rate:
                  summary: invalid_tax_rate
                  value:
                    code: invalid_tax_rate
                    detail: >-
                      A line carries a tax rate the tax agency does not accept
                      for that tax type on the current date. Spanish VAT (`vat`)
                      currently accepts 0, 4, 10 and 21. Rated types require a
                      rate; rate-free types must omit it.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invalid_tax_rate
                invoice_already_replaced:
                  summary: invoice_already_replaced
                  value:
                    code: invoice_already_replaced
                    detail: >-
                      The invoice referenced by `rectifies.invoice_id` has
                      already been replaced by a substitution rectificativa.
                      Rectify the replacement instead.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invoice_already_replaced
                invoice_already_voided:
                  summary: invoice_already_voided
                  value:
                    code: invoice_already_voided
                    detail: >-
                      The invoice referenced by `rectifies.invoice_id` was
                      voided (anulada) and cannot be rectified.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invoice_already_voided
                invoice_not_family_tip:
                  summary: invoice_not_family_tip
                  value:
                    code: invoice_not_family_tip
                    detail: >-
                      The invoice referenced by `rectifies.invoice_id` is not
                      the active head of its correction chain. A later
                      rectificativa already supersedes it; rectify that one
                      instead.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invoice_not_family_tip
                invoice_not_rectifiable_at_aeat:
                  summary: invoice_not_rectifiable_at_aeat
                  value:
                    code: invoice_not_rectifiable_at_aeat
                    detail: >-
                      The invoice referenced by `rectifies.invoice_id` cannot be
                      rectified given its tax-agency registration state: it was
                      rejected, skipped, or was never registered.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invoice_not_rectifiable_at_aeat
                invoice_pending_at_aeat:
                  summary: invoice_pending_at_aeat
                  value:
                    code: invoice_pending_at_aeat
                    detail: >-
                      The invoice referenced by `rectifies.invoice_id` is still
                      pending registration at the tax agency. Wait until its
                      `verifactu.status` leaves `pending` before rectifying it.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#invoice_pending_at_aeat
                line_item_without_tax_items:
                  summary: line_item_without_tax_items
                  value:
                    code: line_item_without_tax_items
                    detail: >-
                      Every line item on a rectificativa must carry a tax. A
                      line was submitted without one.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#line_item_without_tax_items
                reason_incompatible_with_recipient:
                  summary: reason_incompatible_with_recipient
                  value:
                    code: reason_incompatible_with_recipient
                    detail: >-
                      The rectification `reason` is incompatible with the
                      recipient identification. Insolvency (concurso) and
                      uncollectible (incobrable) corrections restrict the
                      accepted recipient tax id types.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#reason_incompatible_with_recipient
                recipient_overrides_not_allowed_for_differences:
                  summary: recipient_overrides_not_allowed_for_differences
                  value:
                    code: recipient_overrides_not_allowed_for_differences
                    detail: >-
                      A `recipient` block is not allowed on a rectificativa por
                      diferencias: the recipient is inherited from the corrected
                      invoice. Omit it, or use `method: "substitution"` to
                      restate the recipient.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#recipient_overrides_not_allowed_for_differences
                rectified_amounts_required_for_substitution:
                  summary: rectified_amounts_required_for_substitution
                  value:
                    code: rectified_amounts_required_for_substitution
                    detail: >-
                      A rectificativa por sustitución against an external
                      original requires `rectified_amounts` (the base, tax and
                      optional surcharge of the original), which the tax agency
                      needs and cannot be inferred.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#rectified_amounts_required_for_substitution
                rectified_invoice_not_found:
                  summary: rectified_invoice_not_found
                  value:
                    code: rectified_invoice_not_found
                    detail: >-
                      No invoice matches the `rectifies.invoice_id` in this
                      environment. Note that test and live keys see different
                      invoices, and the id must be an `inv_`-prefixed Finseed
                      identifier.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#rectified_invoice_not_found
                rectifying_series_invalid:
                  summary: rectifying_series_invalid
                  value:
                    code: rectifying_series_invalid
                    detail: >-
                      The `number_series_id` does not name a usable rectifying
                      series: it is malformed, does not exist in this
                      environment, or is a standard series. Rectificativas are
                      issued on rectifying series.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#rectifying_series_invalid
                replacement_total_negative:
                  summary: replacement_total_negative
                  value:
                    code: replacement_total_negative
                    detail: >-
                      This rectificativa por sustitución has a negative net
                      total. A replacement invoice restates the full amount,
                      which cannot be below zero.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#replacement_total_negative
                simplified_amount_exceeded:
                  summary: simplified_amount_exceeded
                  value:
                    code: simplified_amount_exceeded
                    detail: >-
                      Simplified invoices cannot exceed 3,000 EUR including tax.
                      Issue a complete invoice with an identified recipient
                      instead.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#simplified_amount_exceeded
                simplified_incompatible_tax_type:
                  summary: simplified_incompatible_tax_type
                  value:
                    code: simplified_incompatible_tax_type
                    detail: >-
                      A tax type on this invoice is incompatible with a
                      simplified invoice (reverse charge requires an identified
                      recipient). Issue a complete invoice instead.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#simplified_incompatible_tax_type
                tax_id_type_country_mismatch:
                  summary: tax_id_type_country_mismatch
                  value:
                    code: tax_id_type_country_mismatch
                    detail: >-
                      The tax_id_type is incompatible with the tax_id_country.
                      es_nif and not_registered require ES, eu_vat requires an
                      EU country other than ES, and official_document,
                      residence_certificate and other require a country other
                      than ES.
                    errors: []
                    doc_url: >-
                      https://www.finseed.es/docs/api-reference/errors#tax_id_type_country_mismatch
        '429':
          description: >-
            The per-key rate limit for this endpoint was exceeded. The response
            carries a `Retry-After` header with the seconds to wait. Spread out
            bursts or batch your work; sustained limits are documented per
            endpoint.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: rate_limited
                detail: >-
                  Too many requests for this endpoint with this API key. Wait
                  for the interval in the Retry-After header and try again.
                errors: []
                doc_url: https://www.finseed.es/docs/api-reference/errors#rate_limited
        '500':
          description: >-
            An unexpected error occurred on our side. No partial work is
            persisted, so the request can be retried safely.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: internal_error
                detail: >-
                  Something went wrong on our side. The request did not complete
                  and can be retried safely.
                errors: []
                doc_url: >-
                  https://www.finseed.es/docs/api-reference/errors#internal_error
        '503':
          description: >-
            Complete invoices validate the recipient tax id against the census
            (AEAT or VIES) at creation time. When that external service is down,
            creation fails with this code and nothing is persisted. Retry later;
            sending the same `Idempotency-Key` makes the retry safe.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                code: tax_id_validation_unavailable
                detail: >-
                  The tax census service (AEAT/VIES) is temporarily unavailable,
                  so the recipient tax id could not be verified and the invoice
                  was not created. Retry in a few minutes; with the same
                  Idempotency-Key the retry is safe.
                errors: []
                doc_url: >-
                  https://www.finseed.es/docs/api-reference/errors#tax_id_validation_unavailable
components:
  schemas:
    InvoiceCreateRequest:
      oneOf:
        - type: object
          properties:
            number_series_id:
              description: >-
                Number series to issue on (see the Number Series resource).
                Defaults to the environment default series. For an ordinary
                invoice this must be a standard series; for a rectificativa (a
                `rectifies` block) it must be a rectifying series.
              example: ns_clx456def789
              type: string
            rectifies:
              type: object
              properties:
                method:
                  type: string
                  enum:
                    - differences
                    - substitution
                  description: >-
                    How to correct the original. `differences` books only the
                    delta; `substitution` replaces the original in full.
                  example: differences
                reason:
                  description: >-
                    Why the original is being corrected (drives the AEAT R1-R4
                    code). Defaults to `correction` (R1). Use `insolvency` (R2)
                    for concurso, `uncollectible` (R3) for créditos incobrables,
                    `other` (R4) otherwise. Simplified invoices always register
                    as R5.
                  example: correction
                  type: string
                  enum:
                    - correction
                    - insolvency
                    - uncollectible
                    - other
                invoice_id:
                  description: >-
                    Opaque id of the invoice to correct, when it was issued
                    through Finseed. Mutually exclusive with `external`.
                  example: inv_clx123abc456
                  type: string
                external:
                  type: object
                  properties:
                    number:
                      type: string
                      minLength: 1
                      maxLength: 60
                      description: >-
                        Invoice number of the external original, exactly as it
                        was issued.
                      example: F-2025-091
                    issued_on:
                      type: string
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      description: >-
                        Issue date of the external original as a plain calendar
                        date (YYYY-MM-DD).
                      example: '2025-03-14'
                    rectified_amounts:
                      type: object
                      properties:
                        base:
                          type: integer
                          description: >-
                            Taxable base of the external original, in minor
                            units (cents).
                          example: 100000
                        tax:
                          type: integer
                          description: >-
                            Tax amount of the external original, in minor units
                            (cents).
                          example: 21000
                        surcharge:
                          description: >-
                            Recargo de equivalencia surcharge of the external
                            original, in minor units (cents). Omit when it does
                            not apply.
                          example: 0
                          type: integer
                      required:
                        - base
                        - tax
                      additionalProperties: false
                      description: >-
                        The original amounts the tax agency needs to register a
                        substitution against an external original (its
                        `ImporteRectificación`). Required when `method` is
                        `substitution`.
                  required:
                    - number
                    - issued_on
                  additionalProperties: false
                  description: >-
                    The original this rectificativa corrects when it was NOT
                    issued through Finseed (a pre-Finseed invoice a migrated
                    merchant rectifies).
              required:
                - method
              additionalProperties: false
              description: >-
                Turns this request into a rectificativa (corrective invoice).
                Reference the original with exactly one of `invoice_id` (issued
                through Finseed) or `external` (issued elsewhere). Omit the
                whole block to issue an ordinary invoice.
            operation_date:
              description: >-
                Date the underlying operation took place, as a calendar day
                (`YYYY-MM-DD`) interpreted in the Europe/Madrid timezone. Must
                be an existing calendar day between 2025-01-01 and today. When
                omitted, or when it equals the issue date, the invoice carries
                the issue date as its operation date. Not supported together
                with a `rectifies` block.
              example: '2025-06-15'
              type: string
              pattern: ^(\d{4})-(\d{2})-(\d{2})$
            line_items:
              minItems: 1
              maxItems: 500
              type: array
              items:
                type: object
                properties:
                  description:
                    type: string
                    minLength: 1
                    maxLength: 500
                    description: Description of the goods or service.
                    example: Consulting services
                  quantity:
                    type: integer
                    minimum: 1
                    description: Number of units billed on this line.
                    example: 2
                  unit_amount:
                    type: integer
                    description: >-
                      Net price of a single unit before tax, in minor units
                      (cents). Negative values create discount lines. Line and
                      invoice totals are computed server-side from quantity,
                      unit_amount and the tax rate.
                    example: 4150
                  tax:
                    type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - vat
                          - igic
                          - ipsi
                          - es_exempt
                          - es_inversion_sujeto_pasivo
                          - es_non_taxable
                          - es_non_taxable_localization
                          - eu_oss
                          - eu_b2b
                          - eu_b2b_services
                          - export
                        description: >-
                          Tax category for this line. `vat`, `igic`, `ipsi` and
                          `eu_oss` require a `rate`; the remaining types are
                          rate-free (exemptions, reverse charge, non-taxable,
                          intra-EU, export).
                        example: vat
                      rate:
                        description: >-
                          Tax rate as a percentage with up to two decimals (21
                          means 21%); more precision is rejected, never rounded.
                          Required for `vat`, `igic`, `ipsi` and `eu_oss`; omit
                          it for rate-free types.
                        example: 21
                        type: number
                        minimum: 0
                        maximum: 100
                    required:
                      - type
                    additionalProperties: false
                    description: The tax applied to a line.
                required:
                  - description
                  - quantity
                  - unit_amount
                  - tax
                additionalProperties: false
                description: A line to bill.
              description: The lines to bill. At least one.
            recargo_equivalencia:
              description: >-
                Applies the Spanish recargo de equivalencia regime: every VAT
                line gains its legally paired surcharge (21%→5.2%, 10%→1.4%,
                4%→0.5%), computed server-side.
              example: false
              type: boolean
            footer_notes:
              description: Free-form text printed at the bottom of the invoice PDF.
              example: Pago a 30 días.
              type: string
              maxLength: 2000
            type:
              type: string
              const: complete
              description: >-
                A complete invoice: the recipient is identified and their tax id
                is validated against the census. On a linked rectificativa (a
                `rectifies.invoice_id`) the recipient is inherited from the
                corrected invoice and may be omitted; when supplied on a
                substitution it restates the recipient.
            recipient:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                  description: >-
                    Name of the recipient, person or business. Validated against
                    the tax census (AEAT/VIES) together with tax_id.
                  example: ACME, S.L.
                company_name:
                  description: >-
                    Company name when it differs from `name` (e.g. a personal
                    name plus a trade name). Usually omitted.
                  example: ACME Corporación, S.L.
                  type: string
                  maxLength: 200
                tax_id:
                  type: string
                  minLength: 3
                  maxLength: 50
                  description: >-
                    Tax identifier of the recipient (e.g. Spanish NIF/CIF or EU
                    VAT number). Validated just-in-time against AEAT or VIES.
                  example: B12345678
                tax_id_type:
                  description: >-
                    Kind of tax identifier. Omit it together with tax_id_country
                    to auto-detect both from the tax_id format and country. When
                    provided, tax_id_country may be omitted if the type implies
                    it: es_nif and not_registered imply ES, and eu_vat derives
                    it from the VAT prefix. The other types require an explicit
                    tax_id_country.
                  example: es_nif
                  type: string
                  enum:
                    - es_nif
                    - eu_vat
                    - passport
                    - official_document
                    - residence_certificate
                    - other
                    - not_registered
                tax_id_country:
                  description: >-
                    ISO 3166-1 alpha-2 country the tax id belongs to. Optional
                    when derivable from tax_id_type (es_nif and not_registered
                    imply ES; eu_vat derives it from the VAT prefix); required
                    for passport, official_document, residence_certificate and
                    other. A pair that contradicts the tax_id_type is rejected.
                  example: ES
                  type: string
                  minLength: 2
                  maxLength: 2
                email:
                  description: >-
                    Recipient email. When the environment has automatic invoice
                    emails enabled, the invoice is sent to this address once the
                    tax agency accepts it.
                  example: cliente@example.com
                  type: string
                  format: email
                  pattern: >-
                    ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                address:
                  type: object
                  properties:
                    line1:
                      type: string
                      minLength: 1
                      maxLength: 200
                      description: Street address.
                      example: Calle Mayor 1
                    line2:
                      description: Additional address line.
                      example: Planta 2
                      type: string
                      maxLength: 200
                    postal_code:
                      type: string
                      minLength: 1
                      maxLength: 20
                      description: Postal code.
                      example: '28001'
                    city:
                      type: string
                      minLength: 1
                      maxLength: 100
                      description: City.
                      example: Madrid
                    country:
                      type: string
                      minLength: 2
                      maxLength: 2
                      description: ISO 3166-1 alpha-2 country code.
                      example: ES
                  required:
                    - line1
                    - postal_code
                    - city
                    - country
                  additionalProperties: false
                  description: Postal address of the recipient.
              required:
                - name
                - tax_id
                - address
              additionalProperties: false
              description: The identified recipient of a complete invoice.
          required:
            - line_items
            - type
          additionalProperties: false
        - type: object
          properties:
            number_series_id:
              description: >-
                Number series to issue on (see the Number Series resource).
                Defaults to the environment default series. For an ordinary
                invoice this must be a standard series; for a rectificativa (a
                `rectifies` block) it must be a rectifying series.
              example: ns_clx456def789
              type: string
            rectifies:
              type: object
              properties:
                method:
                  type: string
                  enum:
                    - differences
                    - substitution
                  description: >-
                    How to correct the original. `differences` books only the
                    delta; `substitution` replaces the original in full.
                  example: differences
                reason:
                  description: >-
                    Why the original is being corrected (drives the AEAT R1-R4
                    code). Defaults to `correction` (R1). Use `insolvency` (R2)
                    for concurso, `uncollectible` (R3) for créditos incobrables,
                    `other` (R4) otherwise. Simplified invoices always register
                    as R5.
                  example: correction
                  type: string
                  enum:
                    - correction
                    - insolvency
                    - uncollectible
                    - other
                invoice_id:
                  description: >-
                    Opaque id of the invoice to correct, when it was issued
                    through Finseed. Mutually exclusive with `external`.
                  example: inv_clx123abc456
                  type: string
                external:
                  type: object
                  properties:
                    number:
                      type: string
                      minLength: 1
                      maxLength: 60
                      description: >-
                        Invoice number of the external original, exactly as it
                        was issued.
                      example: F-2025-091
                    issued_on:
                      type: string
                      pattern: ^\d{4}-\d{2}-\d{2}$
                      description: >-
                        Issue date of the external original as a plain calendar
                        date (YYYY-MM-DD).
                      example: '2025-03-14'
                    rectified_amounts:
                      type: object
                      properties:
                        base:
                          type: integer
                          description: >-
                            Taxable base of the external original, in minor
                            units (cents).
                          example: 100000
                        tax:
                          type: integer
                          description: >-
                            Tax amount of the external original, in minor units
                            (cents).
                          example: 21000
                        surcharge:
                          description: >-
                            Recargo de equivalencia surcharge of the external
                            original, in minor units (cents). Omit when it does
                            not apply.
                          example: 0
                          type: integer
                      required:
                        - base
                        - tax
                      additionalProperties: false
                      description: >-
                        The original amounts the tax agency needs to register a
                        substitution against an external original (its
                        `ImporteRectificación`). Required when `method` is
                        `substitution`.
                  required:
                    - number
                    - issued_on
                  additionalProperties: false
                  description: >-
                    The original this rectificativa corrects when it was NOT
                    issued through Finseed (a pre-Finseed invoice a migrated
                    merchant rectifies).
              required:
                - method
              additionalProperties: false
              description: >-
                Turns this request into a rectificativa (corrective invoice).
                Reference the original with exactly one of `invoice_id` (issued
                through Finseed) or `external` (issued elsewhere). Omit the
                whole block to issue an ordinary invoice.
            operation_date:
              description: >-
                Date the underlying operation took place, as a calendar day
                (`YYYY-MM-DD`) interpreted in the Europe/Madrid timezone. Must
                be an existing calendar day between 2025-01-01 and today. When
                omitted, or when it equals the issue date, the invoice carries
                the issue date as its operation date. Not supported together
                with a `rectifies` block.
              example: '2025-06-15'
              type: string
              pattern: ^(\d{4})-(\d{2})-(\d{2})$
            line_items:
              minItems: 1
              maxItems: 500
              type: array
              items:
                type: object
                properties:
                  description:
                    type: string
                    minLength: 1
                    maxLength: 500
                    description: Description of the goods or service.
                    example: Consulting services
                  quantity:
                    type: integer
                    minimum: 1
                    description: Number of units billed on this line.
                    example: 2
                  unit_amount:
                    type: integer
                    description: >-
                      Net price of a single unit before tax, in minor units
                      (cents). Negative values create discount lines. Line and
                      invoice totals are computed server-side from quantity,
                      unit_amount and the tax rate.
                    example: 4150
                  tax:
                    type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - vat
                          - igic
                          - ipsi
                          - es_exempt
                          - es_inversion_sujeto_pasivo
                          - es_non_taxable
                          - es_non_taxable_localization
                          - eu_oss
                          - eu_b2b
                          - eu_b2b_services
                          - export
                        description: >-
                          Tax category for this line. `vat`, `igic`, `ipsi` and
                          `eu_oss` require a `rate`; the remaining types are
                          rate-free (exemptions, reverse charge, non-taxable,
                          intra-EU, export).
                        example: vat
                      rate:
                        description: >-
                          Tax rate as a percentage with up to two decimals (21
                          means 21%); more precision is rejected, never rounded.
                          Required for `vat`, `igic`, `ipsi` and `eu_oss`; omit
                          it for rate-free types.
                        example: 21
                        type: number
                        minimum: 0
                        maximum: 100
                    required:
                      - type
                    additionalProperties: false
                    description: The tax applied to a line.
                required:
                  - description
                  - quantity
                  - unit_amount
                  - tax
                additionalProperties: false
                description: A line to bill.
              description: The lines to bill. At least one.
            recargo_equivalencia:
              description: >-
                Applies the Spanish recargo de equivalencia regime: every VAT
                line gains its legally paired surcharge (21%→5.2%, 10%→1.4%,
                4%→0.5%), computed server-side.
              example: false
              type: boolean
            footer_notes:
              description: Free-form text printed at the bottom of the invoice PDF.
              example: Pago a 30 días.
              type: string
              maxLength: 2000
            type:
              type: string
              const: simplified
              description: >-
                A simplified invoice (ticket): no identified recipient required.
                Total must not exceed 3,000 EUR.
            recipient:
              type: object
              properties:
                name:
                  description: Recipient name, when known.
                  example: Jane Doe
                  type: string
                  minLength: 1
                  maxLength: 200
                email:
                  description: >-
                    Recipient email. When the environment has automatic invoice
                    emails enabled, the invoice is sent to this address once
                    accepted.
                  example: cliente@example.com
                  type: string
                  format: email
                  pattern: >-
                    ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                address:
                  description: Postal address, when known.
                  type: object
                  properties:
                    line1:
                      type: string
                      minLength: 1
                      maxLength: 200
                      description: Street address.
                      example: Calle Mayor 1
                    line2:
                      description: Additional address line.
                      example: Planta 2
                      type: string
                      maxLength: 200
                    postal_code:
                      type: string
                      minLength: 1
                      maxLength: 20
                      description: Postal code.
                      example: '28001'
                    city:
                      type: string
                      minLength: 1
                      maxLength: 100
                      description: City.
                      example: Madrid
                    country:
                      type: string
                      minLength: 2
                      maxLength: 2
                      description: ISO 3166-1 alpha-2 country code.
                      example: ES
                  additionalProperties: false
              additionalProperties: false
              description: >-
                Optional, unvalidated recipient data on a simplified invoice.
                Unknown fields are rejected: to bill an identified recipient
                with a tax_id, create a complete invoice instead.
          required:
            - line_items
            - type
          additionalProperties: false
      description: >-
        The invoice to issue. The invoice number, issue date and totals are
        assigned server-side; the optional `operation_date` is the only date the
        caller sets. Issuance is immediate and the AEAT registration progresses
        asynchronously (poll `verifactu.status`). Include a `rectifies` block to
        issue a rectificativa instead of an ordinary invoice.
    InvoiceValidateResult:
      type: object
      properties:
        valid:
          type: boolean
          const: true
          description: >-
            Always true on a 200: the payload passed every validation the create
            endpoint runs. Failures return the same error responses the create
            endpoint would.
        totals:
          type: object
          properties:
            subtotal:
              type: integer
              description: Net total before tax, in minor units (cents).
              example: 8300
            tax:
              type: integer
              description: Total tax, in minor units (cents).
              example: 1743
            total:
              type: integer
              description: Gross total including tax, in minor units (cents).
              example: 10043
          required:
            - subtotal
            - tax
            - total
          additionalProperties: false
          description: >-
            The exact totals the invoice would carry if created with this
            payload.
      required:
        - valid
        - totals
      additionalProperties: false
      description: Successful dry-run of an invoice creation payload.
    ErrorEnvelope:
      type: object
      properties:
        code:
          type: string
          description: >-
            Stable, machine-readable error code. The branch key. This is an
            extensible enum: new values may be added in the future, so clients
            must tolerate values not listed here. Known values: invalid_request,
            unauthorized, invoice_not_found, download_link_expired,
            number_series_not_found, number_series_prefix_taken,
            number_series_in_use, customer_not_found, customer_ambiguous,
            idempotency_conflict, rate_limited, invalid_number_series,
            invalid_tax_rate, invalid_tax_data, invalid_tax_id,
            tax_id_type_country_mismatch, insufficient_recipient_data,
            simplified_amount_exceeded, simplified_incompatible_tax_type,
            invalid_recargo_equivalencia, aeat_mandate_not_approved,
            no_active_subscription, tax_id_validation_unavailable,
            invalid_rectifies_reference, rectified_invoice_not_found,
            invoice_already_voided, invoice_already_replaced,
            invoice_not_family_tip, invoice_pending_at_aeat,
            invoice_not_rectifiable_at_aeat, family_balance_below_zero,
            replacement_total_negative, reason_incompatible_with_recipient,
            recipient_overrides_not_allowed_for_differences,
            rectifying_series_invalid, external_reference_invalid,
            external_reference_matches_existing_invoice,
            rectified_amounts_required_for_substitution,
            line_item_without_tax_items, internal_error.
          example: invalid_request
        detail:
          type: string
          description: Human-readable, context-specific explanation.
          example: The query parameters are not valid.
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
                description: Location of the offending value (JSON path).
                example: limit
              code:
                type: string
                description: Machine-readable validation issue code.
                example: too_big
              message:
                type: string
                description: Human-readable explanation of the field-level issue.
                example: Number must be less than or equal to 100
            required:
              - field
              - code
              - message
            additionalProperties: false
          description: >-
            Field-level issues. Always present; empty unless this is a
            validation failure.
        doc_url:
          type: string
          description: Link to the reference documentation for this error code.
          example: https://www.finseed.es/docs/api-reference/errors#invalid_request
      required:
        - code
        - detail
        - errors
        - doc_url
      additionalProperties: false
      description: >-
        Uniform error body returned for every non-2xx response
        (application/json).
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key sent as a bearer token in the `Authorization` header.

````