openapi: 3.0.3
servers:
- url: https://api.verifacti.com/
info:
  title: TicketBai API Documentation
  contact:
    email: info@verifacti.com
    name: Contact
    url: https://www.verifacti.com
  description: |2

    &nbsp;

    Here you will find the TicketBai API documentation, the system analogous to VeriFactu for the Basque Country. It is a completely separate API from
    the VeriFactu API, although it is very similar. The only significant changes are in the methods for creating and modifying invoices. This
    is because the APIs of each tax authority are different. However, the general structure of these methods is the same.

    &nbsp;

    The VeriFactu API documentation can be found <a href="https://www.verifacti.com/docs">here</a>.

    &nbsp;

    We have also created a third API to manage different NIFs programmatically. For users who only need to manage
    a few NIFs, this can be done conveniently through our interface. However, sometimes this is not practical and a
    programmatic way to register and deregister different NIFs is needed. For this, you can use our NIFs management API, whose documentation can
    be found <a href="https://www.verifacti.com/nifs-docs">here</a>. This API is included in the price and can be used by any user
    with an active subscription.

    &nbsp;

    <a
      href="https://storage.googleapis.com/verifacti_non_sensitive/postman_ticketbai.json"
      download="tb-docs.json"
      style="
      display: inline-block;
      padding: 6px 12px;
      background-color: #FF6C37;
      color: white;
      text-decoration: none;
      border-radius: 5px;
      font-weight: bold;
      font-family: Arial, sans-serif;
      box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    ">
      Postman Collection
    </a>

    # Comparison between the Basque tax authority APIs and the Verifacti API

    The APIs that the Basque tax authorities have made available to taxpayers to submit invoices require the following steps:

    &nbsp;

    <ol style="list-style: decimal;">
      <li>Create a digital fingerprint using the invoice data and the taxpayer's NIF.</li>
      <li>Compose an XML file with the invoice data, the fingerprint and the previous submission's fingerprint.</li>
      <li>Digitally sign the XML file using an XAdES-EPES format.</li>
      <li>Submit the XML file to the corresponding tax authority via an authenticated call using a qualified recognized electronic certificate.</li>
      <li>In parallel, a QR code must be generated containing the invoice verification URL as well as the TicketBai code to include in the invoice delivered to the recipient.</li>
      <li>Store the data for each invoice.</li>
    </ol>

    &nbsp;

    Using our TicketBai API, all these steps are simplified into a single step:

    &nbsp;

    <ol style="list-style: decimal;">
      <li>Make a single call (without certificate) with the invoice data in JSON format.</li>
    </ol>

    &nbsp;

    Our API immediately responds with the QR code and the TicketBai code so you can add them directly to the invoice. We take care of
    the fingerprint, the XML files, the digital signature, the QR code, the TicketBai code, the authenticated call and the invoice storage.

    &nbsp;

    At any time you can check the status of all your submissions and invoices via API. Additionally, you will have a simple dashboard
    to do so more conveniently. This can be especially useful when doing initial testing and integration. There
    you will also find examples of the different calls and even a terminal so you can test without needing to use
    POSTMAN, for example.

    # Idempotency

    The mutation endpoints (`/create`, `/modify` and `/cancel`) accept an optional `Idempotency-Key`
    header for safe retries after a network failure. The key is a printable ASCII string of 1 to 255
    characters and remembered for 24 hours per NIF. Full details and the relevant error codes
    (`400`, `409`, `422`) are documented on each affected endpoint.
paths:
  /ticketbai/health:
    get:
      summary: API Status
      description: |
        This endpoint returns the API key status. It is mainly used to verify that the API is active and to know which NIF, environment and tax authority it refers to.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl 'https://api.verifacti.com/ticketbai/health' \
          --header 'Authorization: Bearer <API_KEY>'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/health'
          headers = {
            'Authorization': 'Bearer <API_KEY>'
          }
          response = requests.get(url, headers=headers)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/health';
          const headers = {
            'Authorization': 'Bearer <API_KEY>'
          };
          fetch(url, { headers })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const response = await axios.get("https://api.verifacti.com/ticketbai/health", {
            headers: {
              "Authorization": "Bearer <API_KEY>"
            },
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/health";

          $headers = [
              "Authorization: Bearer <API_KEY>",
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.verifacti.com/ticketbai/health\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/health"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .GET()
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var response = await client.GetAsync("https://api.verifacti.com/ticketbai/health");

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/health"

          oHttp.Open "GET", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"

          oHttp.send

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      responses:
        "200":
          description: API Status
          content:
            application/json:
              schema:
                type: object
                properties:
                  estado:
                    description: API status.
                    type: string
                    example: OK
                  nif:
                    description: Taxpayer's NIF.
                    type: string
                    example: B75777847
                  entorno:
                    description: API key environment.
                    type: string
                    example: test
                  hacienda:
                    description: Tax authority corresponding to the NIF.
                    type: string
                    enum:
                    - alava
                    - guipuzcoa
                    - vizcaya
                    example: alava
  /ticketbai/status:
    post:
      summary: Invoice Status
      description: |
        This endpoint allows querying the status of an invoice as registered in our system.
        To check the status of invoicing records, use the GET `/status` endpoint.

        &nbsp;

        To obtain the status of any issued invoice, you can visit the following URLs of the corresponding tax authority:

        <ul style="list-style: disc; margin-top: 6px;">
          <li><a href="https://ticketbai.araba.eus/tbai/consultafacturas/?idioma=es">Álava</a></li>
          <li><a href="https://www.gipuzkoa.eus/es/web/ogasuna/ticketbai/consulta-facturas">Guipuzcoa</a></li>
          <li><a href="https://www.batuz.eus/es/lroe">Vizcaya</a></li>
        </ul>

        In the test environment, invoice data will be stored for a maximum of 90 days.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/status' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data '{
              "serie": "A",
              "numero": "234634",
              "fecha_expedicion": "CURRENT_DATE"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/status'
          headers = {
            'Authorization': 'Bearer <API_KEY>'
          }
          data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          }
          response = requests.post(url, headers=headers, json=data)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/status';
          const headers = {
            'Authorization': 'Bearer <API_KEY>'
          };
          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/status", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/status";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
              "serie": "A",
              "numero": "234634",
              "fecha_expedicion": "CURRENT_DATE"
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n    \"serie\": \"A\",\n    \"numero\": \"234634\",\n    \"fecha_expedicion\": \"CURRENT_DATE\"\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/status\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                              "serie": "A",
                              "numero": "234634",
                              "fecha_expedicion": "CURRENT_DATE"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/status"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
              ""serie"": ""A"",
              ""numero"": ""234634"",
              ""fecha_expedicion"": ""CURRENT_DATE""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/status", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/status"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "    ""serie"": ""A""," & vbCrLf & _
                 "    ""numero"": ""234634""," & vbCrLf & _
                 "    ""fecha_expedicion"": ""CURRENT_DATE""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - serie
              - numero
              - fecha_expedicion
              properties:
                serie:
                  type: string
                  example: A
                  maxLength: 20
                  description: Invoice series.
                numero:
                  type: string
                  minLength: 1
                  maxLength: 20
                  pattern: (\s*[^\s]\s*)+
                  example: "234634"
                  description: Invoice number.
                fecha_expedicion:
                  type: string
                  pattern: ^\d{2}-\d{2}-\d{4}$
                  example: CURRENT_DATE
                  description: Invoice issue date. Cannot be a date later than the current date.
      responses:
        "200":
          description: Invoice Status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/estadoFactura"
        "500":
          description: Server error
    get:
      summary: Record Status
      description: |
        This endpoint allows checking the current status of a previously submitted invoicing record. Immediately after submitting a record, it is
        always in `Pendiente` (Pending) status, queued and will typically be processed within a few seconds.

        &nbsp;

        It is important to understand that, although uncommon, multiple invoicing records may exist for the same invoice. For example, an invoice that was created
        and subsequently cancelled would have two different invoicing records (one for creation and one for cancellation). This endpoint returns the status of the
        invoicing record, which does not necessarily correspond to the invoice status.

        &nbsp;

        In the test environment, invoicing record data will be stored for a maximum of 90 days.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl 'https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c' \
          --header 'Authorization: Bearer <API_KEY>'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c'
          headers = {
            'Authorization': 'Bearer <API_KEY>'
          }
          response = requests.get(url, headers=headers)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c';
          const headers = {
            'Authorization': 'Bearer <API_KEY>'
          };
          fetch(url, { headers })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const response = await axios.get("https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c", {
            headers: {
              "Authorization": "Bearer <API_KEY>"
            },
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c";

          $headers = [
              "Authorization: Bearer <API_KEY>",
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .GET()
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var response = await client.GetAsync("https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c");

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/status?uuid=b018ced3-b362-4494-8776-9eefff1c160c"

          oHttp.Open "GET", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"

          oHttp.send

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      parameters:
      - in: query
        name: uuid
        required: true
        schema:
          type: string
        example: b018ced3-b362-4494-8776-9eefff1c160c
        description: Unique record identifier received as a response at the time of submission.
      responses:
        "200":
          description: Record Status
          content:
            application/json:
              schema:
                type: object
                properties:
                  nif:
                    description: Invoice issuer's NIF.
                    type: string
                  serie:
                    description: Invoice series.
                    type: string
                  numero:
                    description: Invoice number.
                    type: string
                  fecha_expedicion:
                    description: Invoice issue date.
                    type: string
                  operacion:
                    type: string
                    description: |
                      In general, there are five types of operations:
                      <ol style="list-style: disc;">
                        <li>Alta: standard invoice submission. Endpoint: <code>/create</code>.</li>
                        <li>Modificacion: invoice modification. Endpoint: <code>/modify</code> with `accion` set to MODIFICAR. Not available in Vizcaya.</li>
                        <li>Subsanacion: invoice rectification. Endpoint: <code>/modify</code> with `accion` set to SUBSANAR. Not available in Vizcaya.</li>
                        <li>Anulacion: standard invoice cancellation. Endpoint: <code>/cancel</code>.</li>
                        <li>Anulación (rechazo previo): cancellation of a previously rejected invoice. Endpoint: <code>/cancel</code> with `rechazo_previo=true`. Not available in Vizcaya.</li>
                      </ol>
                  estado:
                    description: |
                      Invoicing record status:
                      <ol style="list-style: disc;">
                        <li>Pendiente: Record queued and not yet processed.</li>
                        <li>Correcto: Record successfully processed by the corresponding tax authority.</li>
                        <li>Aceptado con errores: Record accepted with errors.</li>
                        <li>Incorrecto: Record considered incorrect.</li>
                        <li>Anulada: Cancellation record successfully processed by the corresponding tax authority.</li>
                        <li>Error servidor Hacienda: Tax authority server error. The invoicing record will be retried.</li>
                      </ol>
                    type: string
                  url:
                    description: QR code verification URL.
                    type: string
                  qr:
                    description: Base 64 QR code containing the URL.
                    type: string
                  tbai:
                    description: TicketBai code.
                    type: string
                  mensaje_error:
                    description: Error description as reported by the corresponding tax authority.
                    type: string
                example:
                  nif: A15022510
                  serie: A
                  numero: "34547"
                  fecha_expedicion: CURRENT_DATE
                  operacion: Alta
                  url: https://pruebas-ticketbai.araba.eus/tbai/qrtbai/?id=TBAI-A15022510-021224-mwUG7NRo2ZNxp-010&s=A&nf=34547&i=242&cr=010
                  qr: jBBWRw0KGgoABAANSUhEAH0CAIAAABE...
                  tbai: TBAI-B05434202-021224-mwUG7NRo2ZNxp-010
                  estado: Correcto
        "404":
          description: Record not found
        "500":
          description: Server error
  /ticketbai/create:
    post:
      summary: Create New Invoice
      description: |
        This endpoint creates a new invoicing record. There are three response states and it is important to understand what happens in each case:
        <br><br>
        <ol style="list-style: disc;">
          <li>
            <strong>200</strong>: Our API accepts the request and queues it for processing. In this case, the response contains the QR code in base 64, the TicketBai code
            and the verification URL contained in the QR code. Additionally, the record status is returned, which will always be <code style="color: black;">Pendiente</code> (Pending), indicating
            that it has been queued but not yet processed.
            <br>
            It is important to understand that this status only indicates that the invoicing record will be generated and sent to the tax authority, which does not necessarily mean that the
            tax authority will accept it. Our API performs numerous validations to minimize the risk of this happening, but it can occur.
            <br>
            The submission status can be checked using the GET <code style="color: black;">/status</code> endpoint with the returned <code style="color: black;">uuid</code>. We also provide webhooks to receive notifications about
            invoicing record statuses. The webhook documentation can be
            found <a href='https://www.verifacti.com/nifs-docs#tag/Webhooks' target='_blank'>here</a>.
            <br><br>
          </li>
          <li>
            <strong>400</strong>: Our API rejects the call due to an error in the submitted JSON. The invoicing record is not generated and no communication with the tax authority will occur.
            <br>
            We perform numerous checks to minimize the risk of the tax authority rejecting the submission. The response will include a message with the error description.
            Validations range from simple checks such as ensuring no required field is missing to more complex ones such as verifying that the recipient's NIF is registered at the AEAT.
            <br><br>
          </li>
          <li>
            <strong>500</strong>: Server error. This is a generic error that should not occur. If it does, the invoicing record is not generated and,
            therefore, no submission to the tax authority takes place. The client should retry the call later.
          </li>
        </ol>

        &nbsp;

        The complete documentation of the corresponding endpoint for the AEAT API can be found
        <a href='https://www.agenciatributaria.es/static_files/AEAT_Desarrolladores/EEDD/IVA/VERI-FACTU/Validaciones_Errores_Veri-Factu.pdf' target='_blank'>here</a>.

        &nbsp;

        This endpoint also accepts an optional `Idempotency-Key` header. If present, retries of the same logical request with the same key replay the original
        response (including the `Idempotent-Replayed: true` response header and the echoed `Idempotency-Key`).
        Keys are scoped per NIF and remembered for 24 hours.
        Reusing the same key with a different body returns 422; a concurrent retry while the first is still
        in flight returns 409. See the "Idempotency" section at the top of this documentation for more details.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/create' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data-raw '{
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE",
            "simplificada": false,
            "nif": "A15022510",
            "nombre": "Empresa de ejemplo SL",
            "direccion": "direccion cliente",
            "cp": "48992",
            "descripcion": "descripcion de la factura",
            "tipo_operacion": "servicios",
            "lineas": [{
                "descripcion": "linea 1",
                "cantidad": "2",
                "importe_unitario": "100.00",
                "importe_total": "242.00"
            }],
            "desglose_iva": [
              {
                "base_imponible": "200",
                "tipo_impositivo": "21",
                "cuota_impuesto": "42"
              }
            ],
            "importe_total": "242.00"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/create'
          headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          }
          data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': False,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': "2",
                'importe_unitario': "100.00",
                'importe_total': "242.00"
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': "200",
                'tipo_impositivo': "21",
                'cuota_impuesto': "42"
              }
            ],
            'importe_total': "242.00"
          }
          response = requests.post(url, headers=headers, json=data)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/create';
          const headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          };
          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': false,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': '2',
                'importe_unitario': '100.00',
                'importe_total': '242.00'
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': "200",
                'tipo_impositivo': "21",
                'cuota_impuesto': "42"
              }
            ],
            'importe_total': '242.00'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': false,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': '2',
                'importe_unitario': '100.00',
                'importe_total': '242.00'
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': "200",
                'tipo_impositivo': "21",
                'cuota_impuesto': "42"
              }
            ],
            'importe_total': '242.00'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/create", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/create";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE",
            "simplificada": false,
            "nif": "A15022510",
            "nombre": "Empresa de ejemplo SL",
            "direccion": "direccion cliente",
            "cp": "48992",
            "descripcion": "descripcion de la factura",
            "tipo_operacion": "servicios",
            "lineas": [{
                "descripcion": "linea 1",
                "cantidad": "2",
                "importe_unitario": "100.00",
                "importe_total": "242.00"
            }],
            "desglose_iva": [
              {
                "base_imponible": "200",
                "tipo_impositivo": "21",
                "cuota_impuesto": "42"
              }
            ],
            "importe_total": "242.00"
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n  \"serie\": \"A\",\n  \"numero\": \"234634\",\n  \"fecha_expedicion\": \"CURRENT_DATE\",\n  \"simplificada\": false,\n  \"nif\": \"A15022510\",\n  \"nombre\": \"Empresa de ejemplo SL\",\n  \"direccion\": \"direccion cliente\",\n  \"cp\": \"48992\",\n  \"descripcion\": \"descripcion de la factura\",\n  \"tipo_operacion\": \"servicios\",\n  \"lineas\": [{\n      \"descripcion\": \"linea 1\",\n      \"cantidad\": \"2\",\n      \"importe_unitario\": \"100.00\",\n      \"importe_total\": \"242.00\"\n  }],\n  \"desglose_iva\": [\n    {\n      \"base_imponible\": \"200\",\n      \"tipo_impositivo\": \"21\",\n      \"cuota_impuesto\": \"42\"\n    }\n  ],\n  \"importe_total\": \"242.00\"\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/create\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                            "serie": "A",
                            "numero": "234634",
                            "fecha_expedicion": "CURRENT_DATE",
                            "simplificada": false,
                            "nif": "A15022510",
                            "nombre": "Empresa de ejemplo SL",
                            "direccion": "direccion cliente",
                            "cp": "48992",
                            "descripcion": "descripcion de la factura",
                            "tipo_operacion": "servicios",
                            "lineas": [{
                                "descripcion": "linea 1",
                                "cantidad": "2",
                                "importe_unitario": "100.00",
                                "importe_total": "242.00"
                            }],
                            "desglose_iva": [
                              {
                                "base_imponible": "200",
                                "tipo_impositivo": "21",
                                "cuota_impuesto": "42"
                              }
                            ],
                            "importe_total": "242.00"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/create"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
            ""serie"": ""A"",
            ""numero"": ""234634"",
            ""fecha_expedicion"": ""CURRENT_DATE"",
            ""simplificada"": false,
            ""nif"": ""A15022510"",
            ""nombre"": ""Empresa de ejemplo SL"",
            ""direccion"": ""direccion cliente"",
            ""cp"": ""48992"",
            ""descripcion"": ""descripcion de la factura"",
            ""tipo_operacion"": ""servicios"",
            ""lineas"": [{
                ""descripcion"": ""linea 1"",
                ""cantidad"": ""2"",
                ""importe_unitario"": ""100.00"",
                ""importe_total"": ""242.00""
            }],
            ""desglose_iva"": [
              {
                ""base_imponible"": ""200"",
                ""tipo_impositivo"": ""21"",
                ""cuota_impuesto"": ""42""
              }
            ],
            ""importe_total"": ""242.00""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/create", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/create"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "  ""serie"": ""A""," & vbCrLf & _
                 "  ""numero"": ""234634""," & vbCrLf & _
                 "  ""fecha_expedicion"": ""CURRENT_DATE""," & vbCrLf & _
                 "  ""simplificada"": false," & vbCrLf & _
                 "  ""nif"": ""A15022510""," & vbCrLf & _
                 "  ""nombre"": ""Empresa de ejemplo SL""," & vbCrLf & _
                 "  ""direccion"": ""direccion cliente""," & vbCrLf & _
                 "  ""cp"": ""48992""," & vbCrLf & _
                 "  ""descripcion"": ""descripcion de la factura""," & vbCrLf & _
                 "  ""tipo_operacion"": ""servicios""," & vbCrLf & _
                 "  ""lineas"": [{" & vbCrLf & _
                 "      ""descripcion"": ""linea 1""," & vbCrLf & _
                 "      ""cantidad"": ""2""," & vbCrLf & _
                 "      ""importe_unitario"": ""100.00""," & vbCrLf & _
                 "      ""importe_total"": ""242.00""" & vbCrLf & _
                 "  }]," & vbCrLf & _
                 "  ""desglose_iva"": [" & vbCrLf & _
                 "    {" & vbCrLf & _
                 "      ""base_imponible"": ""200""," & vbCrLf & _
                 "      ""tipo_impositivo"": ""21""," & vbCrLf & _
                 "      ""cuota_impuesto"": ""42""" & vbCrLf & _
                 "    }" & vbCrLf & _
                 "  ]," & vbCrLf & _
                 "  ""importe_total"": ""242.00""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      parameters:
      - in: header
        name: Idempotency-Key
        required: false
        description: Optional unique key that guarantees retries of the same request don't create duplicates. Printable ASCII string, 1–255 characters. Remembered per NIF for 24 hours.
        schema:
          type: string
          pattern: '^[\x20-\x7E]{1,255}$'
          minLength: 1
          maxLength: 255
          example: 8e1b9c2a-3f4d-4a6b-9c2e-1d2f3e4a5b6c
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - serie
              - numero
              - fecha_expedicion
              - descripcion
              - lineas
              - importe_total
              properties:
                serie:
                  type: string
                  maxLength: 20
                  description: Invoice series.
                numero:
                  type: string
                  minLength: 1
                  maxLength: 20
                  pattern: (\s*[^\s]\s*)+
                  description: Invoice number.
                fecha_expedicion:
                  type: string
                  pattern: \d{2,2}-\d{2,2}-\d{4,4}
                  description: Invoice issue date. Cannot be a date later than the current date.
                descripcion:
                  type: string
                  minLength: 1
                  maxLength: 250
                  description: Invoice description.
                simplificada:
                  type: boolean
                  default: false
                  description: |
                    Indicates whether the invoice is simplified. If not simplified, the `nif` or `id_otro` field must be included. Additionally, the
                    invoice recipient data `nombre`, `cp` and `direccion` must be included.
                nif:
                  type: string
                  example: A15022510
                  description: |
                    NIF of the client to whom the invoice is issued. Required except for simplified invoices or when the `id_otro` field is included.
                    If both `nif` and `id_otro` are included, `nif` will be used.

                    &nbsp;

                    If the `nif` field is included, we validate by default that it is registered at the AEAT, since if it is not, the Basque Regional Tax Authority will reject the submission. If
                    not registered, a 400 error will be returned, meaning the invoicing record has not been generated and no submission to the Basque Regional Tax Authority will occur.

                    &nbsp;

                    For legal entities, it is sufficient for the NIF to be registered. For individuals, the NIF must be registered and the `nombre` must be
                    sufficiently similar to the name appearing in the census.

                    &nbsp;

                    We provide an endpoint to validate the NIF of individuals and legal entities in the NIFs management API. The documentation can be found
                    <a href="https://www.verifacti.com/nifs-docs#tag/NIFs/paths/~1nifs~1validar/post" target="_blank">here</a>.
                id_otro:
                  type: object
                  description: |
                    Identifier for an individual or legal entity other than the NIF. Required except for simplified invoices or when the `nif` field is included.
                    If both `nif` and `id_otro` are included, `nif` will be used.
                  properties:
                    codigo_pais:
                      type: string
                      description: Country code of the individual or legal entity in ISO 3166-1 alpha-2 format. Optional parameter.
                    id_type:
                      type: string
                      enum:
                      - "02"
                      - "03"
                      - "04"
                      - "05"
                      - "06"
                      description: |
                        Identifier type of the individual or legal entity. The different identifier types are:
                        <ol style="list-style: disc;">
                          <li>02: VAT-ID</li>
                          <li>03: Passport</li>
                          <li>04: Official identification document issued by the country or territory of residence</li>
                          <li>05: Residence certificate</li>
                          <li>06: Other supporting document</li>
                        </ol> 
                    id:
                      type: string
                      maxLength: 20
                      description: |
                        Identifier of the individual or legal entity. Up to a maximum of 20 characters is allowed.

                        &nbsp;

                        When the country is intra-community and the `id_type` is `02`, i.e., it corresponds to a VAT number, it will be validated by default
                        that it is in the VIES census. If it is not, the Basque Regional Tax Authority will reject the submission.

                        &nbsp;

                        We provide an endpoint for VAT validation in the VIES census in the NIFs management API.
                        The documentation can be found <a href="https://www.verifacti.com/nifs-docs#tag/NIFs/paths/~1nifs~1validar~1vies/post" target="_blank">here</a>.
                nombre:
                  type: string
                  maxLength: 120
                  description: Full name or company name of the client to whom the invoice is issued. Required except for simplified invoices.
                validar_destinatario:
                  type: boolean
                  default: true
                  description: |
                    If the `nif` field is included, we validate by default that it is registered at the AEAT, since if it is not, the Basque Regional Tax Authority will reject the submission. This requires an
                    additional call on our side. You can disable this validation in the test environment by setting
                    this field to `false`.

                    &nbsp;

                    Similarly, if the `id_otro` field is included with `id_type` equal to `02` and `codigo_pais` of an intra-community country, we validate by default that
                    the VAT is in the VIES census. This validation can be disabled in the test environment by setting this field to `false`.
                cp:
                  type: string
                  maxLength: 20
                  description: Postal code of the client to whom the invoice is issued. Required except for simplified invoices in Álava and Guipúzcoa.
                direccion:
                  type: string
                  maxLength: 250
                  description: Address of the client to whom the invoice is issued. Required except for simplified invoices in Álava and Guipúzcoa.
                sustitucion_simplificada:
                  type: boolean
                  default: false
                  description: Indicates whether the invoice is issued as a replacement for a simplified invoice.
                tipo_operacion:
                  type: string
                  enum:
                  - servicios
                  - bienes
                  default: servicios
                  description: |
                    Operation type. The different operation types are:
                    <ol style="list-style: disc;">
                      <li>servicios: provision of services</li>
                      <li>bienes: delivery of goods</li>
                lineas:
                  type: array
                  minItems: 1
                  maxItems: 1000
                  description: Invoice line items.
                  items:
                    type: object
                    example:
                      descripcion: Venta de zapatos
                      cantidad: "2"
                      importe_unitario: "100.00"
                      importe_total: "242.00"
                    required:
                    - descripcion
                    - cantidad
                    - importe_unitario
                    - importe_total
                    properties:
                      descripcion:
                        type: string
                        minLength: 1
                        maxLength: 250
                        description: Line item description.
                      cantidad:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Line item quantity.
                      importe_unitario:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Unit amount EXCLUDING VAT of the invoice line item.
                      descuento:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Discount amount in euros EXCLUDING VAT of the invoice line item.
                      importe_total:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Total amount INCLUDING VAT of the invoice line item.
                desglose_iva:
                  description: VAT breakdown.
                  maxItems: 12
                  type: array
                  items:
                    type: object
                    properties:
                      base_imponible:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                        description: Non-exempt tax base. The tax rate is applied to the tax base. Required except for exempt invoices.
                      tipo_impositivo:
                        type: string
                        pattern: \d{1,3}(\.\d{0,2})?
                        description: Percentage applied to the tax base to calculate the tax amount. Required except for exempt invoices.
                      cuota_impuesto:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                        description: Output tax. This is the amount resulting from applying the tax rate to the tax base. Required except for exempt invoices.
                      tipo_recargo_equivalencia:
                        description: Associated percentage based on the VAT type.
                        type: string
                        pattern: \d{1,3}(\.\d{0,2})?
                      cuota_recargo_equivalencia:
                        description: Amount resulting from applying the surcharge equivalence rate to the tax base.
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      recargo_equivalencia_o_regimen_simplificado:
                        description: Surcharge equivalence or simplified regime.
                        type: boolean
                        default: false
                detalle_renta:
                  description: Allowed and required only for individuals in Vizcaya.
                  maxItems: 10
                  type: array
                  items:
                    type: object
                    properties:
                      epigrafe:
                        type: string
                        pattern: "[0-9]*"
                        description: Required field. The list of headings can be downloaded <a target="_blank" href="https://www.batuz.eus/descargar_documento.asp?url=fitxategiak/batuz%2Flroe%2Fbatuz_lroe_lista_epigrafes_v1_0_3.xlsx&param=1">here</a>.
                      ingreso_a_computar_irpf_diferente_base_impo_iva:
                        type: string
                        enum:
                        - S
                        - "N"
                        description: Optional field.
                      importe_ingreso_irpf:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                        description: Optional field.
                importe_total:
                  type: string
                  pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                  description: Total invoice amount.
                fecha_operacion:
                  type: string
                  pattern: \d{2,2}-\d{2,2}-\d{4,4}
                  description: Operation date.
                rectificativa:
                  type: object
                  description: Field containing the necessary data in case of a corrective invoice.
                  properties:
                    codigo:
                      type: string
                      description: |
                        Corrective invoice code. The different values are:
                        <ol style="list-style: disc;">
                          <li>R1: Corrective invoice: error based on law and Art. 80 One, Two and Six of the Regional VAT Act</li>
                          <li>R2: Corrective invoice: article 80 Three of the Regional VAT Act</li>
                          <li>R3: Corrective invoice: article 80 Four of the Regional VAT Act</li>
                          <li>R4: Corrective invoice: Other</li>
                          <li>R5: Corrective invoice for simplified invoices</li>
                        </ol>
                    tipo:
                      type: string
                      enum:
                      - S
                      - I
                      description: Indicates whether the corrective invoice is by substitution (`S`) or by differences (`I`).
                    base_rectificada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Tax base of the replaced invoice.
                    cuota_rectificada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Output tax of the replaced invoice.
                    cuota_recargo:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Surcharge equivalence amount of the replaced invoice.
                rectificadas_sustituidas:
                  type: array
                  maxItems: 100
                  description: Rectified or replaced invoices.
                  items:
                    type: object
                    properties:
                      serie:
                        type: string
                        maxLength: 20
                        description: Rectified or replaced invoice series.
                      numero:
                        type: string
                        minLength: 1
                        maxLength: 20
                        pattern: (\s*[^\s]\s*)+
                        description: Rectified or replaced invoice number.
                      fecha_expedicion:
                        type: string
                        pattern: \d{2,2}-\d{2,2}-\d{4,4}
                        description: Rectified or replaced invoice issue date.
                no_sujeta:
                  description: Indicates whether the invoice is not subject to VAT.
                  type: object
                  properties:
                    causa:
                      type: string
                      description: |
                        Cause of non-subjection. The possible values are:
                        <ol style="list-style: disc;">
                          <li>OT: Not subject under article 7 of the Regional VAT Act. Other cases of non-subjection</li>
                          <li>RL: Not subject due to localization rules</li>
                          <li>VT: Not subject, sales made on behalf of third parties (amount not computable for VAT or income tax purposes)</li>
                          <li>IE: Not subject in the TAI due to localization rules, but foreign tax, IPS/IGIC or VAT from another EU member state is charged</li>
                        </ol>
                    importe:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Amount in euros corresponding to the non-subject operation.
                exenta:
                  description: Indicates whether the invoice is exempt.
                  type: object
                  properties:
                    causa_exencion:
                      type: string
                      description: |
                        Cause of exemption. The possible values are:
                        <ol style="list-style: disc;">
                          <li>E1: Exempt under article 20 of the Regional VAT Act</li>
                          <li>E2: Exempt under article 21 of the Regional VAT Act</li>
                          <li>E3: Exempt under article 22 of the Regional VAT Act</li>
                          <li>E4: Exempt under articles 23 and 24 of the Regional VAT Act</li>
                          <li>E5: Exempt under article 25 of the Regional VAT Act</li>
                          <li>E6: Exempt for other reasons</li>
                        </ol>
                    base_imponible:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Exempt tax base in euros corresponding to the cause of exemption.
                especial:
                  type: object
                  description: This section contains additional optional fields.
                  properties:
                    inversion_sujeto_pasivo:
                      type: boolean
                      default: false
                      description: With reverse charge.
                    retencion_soportada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Withholding tax borne.
                    base_imponible_a_coste:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Tax base at cost (for VAT groups – advanced level).
                    clave_regimen:
                      type: string
                      default: "01"
                      enum:
                      - "01"
                      - "02"
                      - "03"
                      - "04"
                      - "05"
                      - "06"
                      - "07"
                      - "08"
                      - "09"
                      - "10"
                      - "11"
                      - "12"
                      - "13"
                      - "14"
                      - "15"
                      - "17"
                      - "19"
                      - "51"
                      - "52"
                      - "53"
                      - "54"
                      description: Special VAT regime key and operations with tax significance.
              example:
                serie: A
                numero: "234634"
                fecha_expedicion: CURRENT_DATE
                simplificada: false
                nif: A15022510
                nombre: Empresa de ejemplo SL
                direccion: direccion cliente
                cp: "48992"
                descripcion: descripcion de la factura
                tipo_operacion: servicios
                lineas:
                - descripcion: linea 1
                  cantidad: "2"
                  importe_unitario: "100.00"
                  importe_total: "242.00"
                desglose_iva:
                - base_imponible: "200.00"
                  tipo_impositivo: "21"
                  cuota_impuesto: "42"
                importe_total: "242.00"
      responses:
        "200":
          description: Invoice created
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    description: Unique record identifier for querying its status.
                    type: string
                    example: ea6eae92-bac6-48c3-baa4-2bbf6b5ee562
                  tbai:
                    description: TicketBai code.
                    type: string
                    example: TBAI-B05434202-021224-mwUG7NRo2ZNxp-010
                  estado:
                    description: Record status. Will always be "Pendiente" (Pending) as a response to a creation. This status can be subsequently checked using the `/status` endpoint.
                    type: string
                    example: Pendiente
                  url:
                    description: QR code verification URL.
                    type: string
                    example: https://pruebas-ticketbai.araba.eus/tbai/qrtbai/?id=TBAI-B05434202-021224-mwUG7NRo2ZNxp-010&s=A&nf=234634&i=242&cr=010
                  qr:
                    description: Base 64 QR code containing the URL.
                    type: string
                    example: jBBWRw0KGgoABAANSUhEAH0CAIAAABE...
        "500":
          description: Server error
  /ticketbai/modify:
    put:
      summary: Modify or Rectify Invoice
      description: |
        This endpoint has been enabled by the Basque tax authorities of Álava and Guipúzcoa for submitting information corresponding to the
        TicketBAI file that has been rejected and/or received with error warnings for not meeting the requirements and conditions established in the
        regulations governing the TicketBAI obligation. It is part of what is known as the ZUZENDU service.

        The fields are exactly the same as those included in the create invoice endpoint, with the addition of the `accion` field indicating whether
        you want to modify or rectify the invoice.

        &nbsp;

        <span style="color: red">IMPORTANT</span>: only available for Álava and Guipúzcoa.

        &nbsp;

        This endpoint also accepts an optional `Idempotency-Key` header. If present, retries of the same logical request with the same key replay the original
        response (including the `Idempotent-Replayed: true` response header and the echoed `Idempotency-Key`).
        Keys are scoped per NIF and remembered for 24 hours.
        Reusing the same key with a different body returns 422; a concurrent retry while the first is still
        in flight returns 409.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request PUT 'https://api.verifacti.com/ticketbai/modify' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data-raw '{
            "accion": "SUBSANAR",
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE",
            "simplificada": false,
            "nif": "A15022510",
            "nombre": "Empresa de ejemplo SL",
            "direccion": "direccion cliente",
            "cp": "48992",
            "descripcion": "descripcion de la factura",
            "tipo_operacion": "servicios",
            "lineas": [{
                "descripcion": "linea 1",
                "cantidad": "2",
                "importe_unitario": "100.00",
                "importe_total": "242.00"
            }],
            "desglose_iva": [{
                "base_imponible": "200",
                "tipo_impositivo": "21",
                "cuota_impuesto": "42"
            }],
            "importe_total": "242.00"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/create'
          headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          }
          data = {
            'accion': 'SUBSANAR',
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': False,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': '2',
                'importe_unitario': '100.00',
                'importe_total': '242.00'
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': '200',
                'tipo_impositivo': '21',
                'cuota_impuesto': '42'
              }
            ],
            'importe_total': '242.00'
          }
          response = requests.put(url, headers=headers, json=data)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/create';
          const headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          };
          const data = {
            'accion': 'SUBSANAR',
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': false,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': '2',
                'importe_unitario': '100.00',
                'importe_total': '242.00'
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': '200',
                'tipo_impositivo': '21',
                'cuota_impuesto': '42'
              }
            ],
            'importe_total': '242.00'
          };
          fetch(url, { headers, method: 'PUT', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'accion': 'SUBSANAR',
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE',
            'simplificada': false,
            'nif': 'A15022510',
            'nombre': 'Empresa de ejemplo SL',
            'direccion': 'direccion cliente',
            'cp': '48992',
            'descripcion': 'descripcion de la factura',
            'tipo_operacion': 'servicios',
            'lineas': [
              {
                'descripcion': 'linea 1',
                'cantidad': '2',
                'importe_unitario': '100.00',
                'importe_total': '242.00'
              }
            ],
            'desglose_iva': [
              {
                'base_imponible': '200',
                'tipo_impositivo': '21',
                'cuota_impuesto': '42'
              }
            ],
            'importe_total': '242.00'
          };

          const response = await axios.put("https://api.verifacti.com/ticketbai/modify", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/modify";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
            "accion": "SUBSANAR",
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE",
            "simplificada": false,
            "nif": "A15022510",
            "nombre": "Empresa de ejemplo SL",
            "direccion": "direccion cliente",
            "cp": "48992",
            "descripcion": "descripcion de la factura",
            "tipo_operacion": "servicios",
            "lineas": [{
                "descripcion": "linea 1",
                "cantidad": "2",
                "importe_unitario": "100.00",
                "importe_total": "242.00"
            }],
            "desglose_iva": [{
                "base_imponible": "200",
                "tipo_impositivo": "21",
                "cuota_impuesto": "42"
            }],
            "importe_total": "242.00"
          }
          JSON;

          curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n  \"accion\": \"SUBSANAR\",\n  \"serie\": \"A\",\n  \"numero\": \"234634\",\n  \"fecha_expedicion\": \"CURRENT_DATE\",\n  \"simplificada\": false,\n  \"nif\": \"A15022510\",\n  \"nombre\": \"Empresa de ejemplo SL\",\n  \"direccion\": \"direccion cliente\",\n  \"cp\": \"48992\",\n  \"descripcion\": \"descripcion de la factura\",\n  \"tipo_operacion\": \"servicios\",\n  \"lineas\": [{\n      \"descripcion\": \"linea 1\",\n      \"cantidad\": \"2\",\n      \"importe_unitario\": \"100.00\",\n      \"importe_total\": \"242.00\"\n  }],\n  \"desglose_iva\": [{\n      \"base_imponible\": \"200\",\n      \"tipo_impositivo\": \"21\",\n      \"cuota_impuesto\": \"42\"\n  }],\n  \"importe_total\": \"242.00\"\n}\n`\n\n\treq, err := http.NewRequest(\"PUT\", \"https://api.verifacti.com/ticketbai/modify\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                            "accion": "SUBSANAR",
                            "serie": "A",
                            "numero": "234634",
                            "fecha_expedicion": "CURRENT_DATE",
                            "simplificada": false,
                            "nif": "A15022510",
                            "nombre": "Empresa de ejemplo SL",
                            "direccion": "direccion cliente",
                            "cp": "48992",
                            "descripcion": "descripcion de la factura",
                            "tipo_operacion": "servicios",
                            "lineas": [{
                                "descripcion": "linea 1",
                                "cantidad": "2",
                                "importe_unitario": "100.00",
                                "importe_total": "242.00"
                            }],
                            "desglose_iva": [{
                                "base_imponible": "200",
                                "tipo_impositivo": "21",
                                "cuota_impuesto": "42"
                            }],
                            "importe_total": "242.00"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/modify"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .PUT(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
            ""accion"": ""SUBSANAR"",
            ""serie"": ""A"",
            ""numero"": ""234634"",
            ""fecha_expedicion"": ""CURRENT_DATE"",
            ""simplificada"": false,
            ""nif"": ""A15022510"",
            ""nombre"": ""Empresa de ejemplo SL"",
            ""direccion"": ""direccion cliente"",
            ""cp"": ""48992"",
            ""descripcion"": ""descripcion de la factura"",
            ""tipo_operacion"": ""servicios"",
            ""lineas"": [{
                ""descripcion"": ""linea 1"",
                ""cantidad"": ""2"",
                ""importe_unitario"": ""100.00"",
                ""importe_total"": ""242.00""
            }],
            ""desglose_iva"": [{
                ""base_imponible"": ""200"",
                ""tipo_impositivo"": ""21"",
                ""cuota_impuesto"": ""42""
            }],
            ""importe_total"": ""242.00""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PutAsync("https://api.verifacti.com/ticketbai/modify", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/modify"

          oHttp.Open "PUT", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "  ""accion"": ""SUBSANAR""," & vbCrLf & _
                 "  ""serie"": ""A""," & vbCrLf & _
                 "  ""numero"": ""234634""," & vbCrLf & _
                 "  ""fecha_expedicion"": ""CURRENT_DATE""," & vbCrLf & _
                 "  ""simplificada"": false," & vbCrLf & _
                 "  ""nif"": ""A15022510""," & vbCrLf & _
                 "  ""nombre"": ""Empresa de ejemplo SL""," & vbCrLf & _
                 "  ""direccion"": ""direccion cliente""," & vbCrLf & _
                 "  ""cp"": ""48992""," & vbCrLf & _
                 "  ""descripcion"": ""descripcion de la factura""," & vbCrLf & _
                 "  ""tipo_operacion"": ""servicios""," & vbCrLf & _
                 "  ""lineas"": [{" & vbCrLf & _
                 "      ""descripcion"": ""linea 1""," & vbCrLf & _
                 "      ""cantidad"": ""2""," & vbCrLf & _
                 "      ""importe_unitario"": ""100.00""," & vbCrLf & _
                 "      ""importe_total"": ""242.00""" & vbCrLf & _
                 "  }]," & vbCrLf & _
                 "  ""desglose_iva"": [{" & vbCrLf & _
                 "      ""base_imponible"": ""200""," & vbCrLf & _
                 "      ""tipo_impositivo"": ""21""," & vbCrLf & _
                 "      ""cuota_impuesto"": ""42""" & vbCrLf & _
                 "  }]," & vbCrLf & _
                 "  ""importe_total"": ""242.00""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      parameters:
      - in: header
        name: Idempotency-Key
        required: false
        description: Optional unique key that guarantees retries of the same request don't create duplicates. Printable ASCII string, 1–255 characters. Remembered per NIF for 24 hours.
        schema:
          type: string
          pattern: '^[\x20-\x7E]{1,255}$'
          minLength: 1
          maxLength: 255
          example: 8e1b9c2a-3f4d-4a6b-9c2e-1d2f3e4a5b6c
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - accion
              - serie
              - numero
              - fecha_expedicion
              - descripcion
              - lineas
              - importe_total
              properties:
                accion:
                  type: string
                  enum:
                  - MODIFICAR
                  - SUBSANAR
                  description: |
                    Action to perform. The possible values are:
                    <ol style="list-style: disc;">
                      <li>
                        SUBSANAR: when needing to correct an invoice that has not been previously received by the corresponding tax authority in the system due to a creation error.
                      </li>
                      <li>
                        MODIFICAR: when needing to correct an invoice that has been previously received by the corresponding tax authority.
                      </li>
                    </ol>
                serie:
                  type: string
                  maxLength: 20
                  description: Invoice series.
                numero:
                  type: string
                  minLength: 1
                  maxLength: 20
                  pattern: (\s*[^\s]\s*)+
                  description: Invoice number.
                fecha_expedicion:
                  type: string
                  pattern: \d{2,2}-\d{2,2}-\d{4,4}
                  description: Invoice issue date. Cannot be a date later than the current date.
                descripcion:
                  type: string
                  minLength: 1
                  maxLength: 250
                  description: Invoice description.
                simplificada:
                  type: boolean
                  default: false
                  description: |
                    Indicates whether the invoice is simplified. If not simplified, the `nif` or `id_otro` field must be included. Additionally, the
                    invoice recipient data `nombre`, `cp` and `direccion` must be included.
                nif:
                  type: string
                  example: A15022510
                  description: |
                    NIF of the client to whom the invoice is issued. Required except for simplified invoices or when the `id_otro` field is included.
                    If both `nif` and `id_otro` are included, `nif` will be used.

                    &nbsp;

                    If the `nif` field is included, we validate by default that it is registered at the AEAT, since if it is not, the Basque Regional Tax Authority will reject the submission. If
                    not registered, a 400 error will be returned, meaning the invoicing record has not been generated and no submission to the Basque Regional Tax Authority will occur.

                    &nbsp;

                    For legal entities, it is sufficient for the NIF to be registered. For individuals, the NIF must be registered and the `nombre` must be
                    sufficiently similar to the name appearing in the census.

                    &nbsp;

                    We provide an endpoint to validate the NIF of individuals and legal entities in the NIFs management API. The documentation can be found
                    <a href="https://www.verifacti.com/nifs-docs#tag/NIFs/paths/~1nifs~1validar/post" target="_blank">here</a>.
                id_otro:
                  type: object
                  description: |
                    Identifier for an individual or legal entity other than the NIF. Required except for simplified invoices or when the `nif` field is included.
                    If both `nif` and `id_otro` are included, `nif` will be used.
                  properties:
                    codigo_pais:
                      type: string
                      description: Country code of the individual or legal entity in ISO 3166-1 alpha-2 format. Optional parameter.
                    id_type:
                      type: string
                      enum:
                      - "02"
                      - "03"
                      - "04"
                      - "05"
                      - "06"
                      description: |
                        Identifier type of the individual or legal entity. The different identifier types are:
                        <ol style="list-style: disc;">
                          <li>02: VAT-ID</li>
                          <li>03: Passport</li>
                          <li>04: Official identification document issued by the country or territory of residence</li>
                          <li>05: Residence certificate</li>
                          <li>06: Other supporting document</li>
                        </ol> 
                    id:
                      type: string
                      maxLength: 20
                      description: |
                        Identifier of the individual or legal entity. Up to a maximum of 20 characters is allowed.

                        &nbsp;

                        When the country is intra-community and the `id_type` is `02`, i.e., it corresponds to a VAT number, it will be validated by default
                        that it is in the VIES census. If it is not, the Basque Regional Tax Authority will reject the submission.

                        &nbsp;

                        We provide an endpoint for VAT validation in the VIES census in the NIFs management API.
                        The documentation can be found <a href="https://www.verifacti.com/nifs-docs#tag/NIFs/paths/~1nifs~1validar~1vies/post" target="_blank">here</a>.
                nombre:
                  type: string
                  maxLength: 120
                  description: Full name or company name of the client to whom the invoice is issued. Required except for simplified invoices.
                validar_destinatario:
                  type: boolean
                  default: true
                  description: |
                    If the `nif` field is included, we validate by default that it is registered at the AEAT, since if it is not, the Basque Regional Tax Authority will reject the submission. This requires an
                    additional call on our side. If you are sure that the recipients' NIFs are registered, you can disable this validation by setting
                    this field to `false`.

                    &nbsp;

                    Similarly, if the `id_otro` field is included with `id_type` equal to `02` and `codigo_pais` of an intra-community country, we validate by default that
                    the VAT is in the VIES census. This validation can be disabled by setting this field to `false`.
                cp:
                  type: string
                  maxLength: 20
                  description: Postal code of the client to whom the invoice is issued. Required except for simplified invoices in Álava and Guipúzcoa.
                direccion:
                  type: string
                  maxLength: 250
                  description: Address of the client to whom the invoice is issued. Required except for simplified invoices in Álava and Guipúzcoa.
                sustitucion_simplificada:
                  type: boolean
                  default: false
                  description: Indicates whether the invoice is issued as a replacement for a simplified invoice.
                tipo_operacion:
                  type: string
                  enum:
                  - servicios
                  - bienes
                  default: servicios
                  description: |
                    Operation type. The different operation types are:
                    <ol style="list-style: disc;">
                      <li>servicios: provision of services</li>
                      <li>bienes: delivery of goods</li>
                lineas:
                  type: array
                  minItems: 1
                  maxItems: 1000
                  description: Invoice line items.
                  items:
                    type: object
                    example:
                      descripcion: Venta de zapatos
                      cantidad: "2"
                      importe_unitario: "100.00"
                      importe_total: "242.00"
                    required:
                    - descripcion
                    - cantidad
                    - importe_unitario
                    - importe_total
                    properties:
                      descripcion:
                        type: string
                        minLength: 1
                        maxLength: 250
                        description: Line item description.
                      cantidad:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Line item quantity.
                      importe_unitario:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Unit amount EXCLUDING VAT of the invoice line item.
                      descuento:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Discount amount in euros EXCLUDING VAT of the invoice line item.
                      importe_total:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,8})?
                        description: Total amount INCLUDING VAT of the invoice line item.
                desglose_iva:
                  description: VAT breakdown.
                  maxItems: 12
                  type: array
                  items:
                    type: object
                    properties:
                      base_imponible:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                        description: Non-exempt tax base. The tax rate is applied to the tax base. Required except for exempt invoices.
                      tipo_impositivo:
                        type: string
                        pattern: \d{1,3}(\.\d{0,2})?
                        description: Percentage applied to the tax base to calculate the tax amount. Required except for exempt invoices.
                      cuota_impuesto:
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                        description: Output tax. This is the amount resulting from applying the tax rate to the tax base. Required except for exempt invoices.
                      tipo_recargo_equivalencia:
                        description: Associated percentage based on the VAT type.
                        type: string
                        pattern: \d{1,3}(\.\d{0,2})?
                      cuota_recargo_equivalencia:
                        description: Amount resulting from applying the surcharge equivalence rate to the tax base.
                        type: string
                        pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      recargo_equivalencia_o_regimen_simplificado:
                        description: Surcharge equivalence or simplified regime.
                        type: boolean
                        default: false
                importe_total:
                  type: string
                  pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                  description: Total invoice amount.
                fecha_operacion:
                  type: string
                  pattern: \d{2,2}-\d{2,2}-\d{4,4}
                  description: Operation date.
                rectificativa:
                  type: object
                  description: Field containing the necessary data in case of a corrective invoice.
                  properties:
                    codigo:
                      type: string
                      description: |
                        Corrective invoice code. The different values are:
                        <ol style="list-style: disc;">
                          <li>R1: Corrective invoice: error based on law and Art. 80 One, Two and Six of the Regional VAT Act</li>
                          <li>R2: Corrective invoice: article 80 Three of the Regional VAT Act</li>
                          <li>R3: Corrective invoice: article 80 Four of the Regional VAT Act</li>
                          <li>R4: Corrective invoice: Other</li>
                          <li>R5: Corrective invoice for simplified invoices</li>
                        </ol>
                    tipo:
                      type: string
                      enum:
                      - S
                      - I
                      description: Indicates whether the corrective invoice is by substitution (`S`) or by differences (`I`).
                    base_rectificada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Tax base of the replaced invoice.
                    cuota_rectificada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Output tax of the replaced invoice.
                    cuota_recargo:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Surcharge equivalence amount of the replaced invoice.
                rectificadas_sustituidas:
                  type: array
                  maxItems: 100
                  description: Rectified or replaced invoices.
                  items:
                    type: object
                    properties:
                      serie:
                        type: string
                        maxLength: 20
                        description: Rectified or replaced invoice series.
                      numero:
                        type: string
                        minLength: 1
                        maxLength: 20
                        pattern: (\s*[^\s]\s*)+
                        description: Rectified or replaced invoice number.
                      fecha_expedicion:
                        type: string
                        pattern: \d{2,2}-\d{2,2}-\d{4,4}
                        description: Rectified or replaced invoice issue date.
                no_sujeta:
                  description: Indicates whether the invoice is not subject to VAT.
                  type: object
                  properties:
                    causa:
                      type: string
                      description: |
                        Cause of non-subjection. The possible values are:
                        <ol style="list-style: disc;">
                          <li>OT: Not subject under article 7 of the Regional VAT Act. Other cases of non-subjection</li>
                          <li>RL: Not subject due to localization rules</li>
                          <li>VT: Not subject, sales made on behalf of third parties (amount not computable for VAT or income tax purposes)</li>
                          <li>IE: Not subject in the TAI due to localization rules, but foreign tax, IPS/IGIC or VAT from another EU member state is charged</li>
                        </ol>
                    importe:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Amount in euros corresponding to the non-subject operation.
                exenta:
                  description: Indicates whether the invoice is exempt.
                  type: object
                  properties:
                    causa_exencion:
                      type: string
                      description: |
                        Cause of exemption. The possible values are:
                        <ol style="list-style: disc;">
                          <li>E1: Exempt under article 20 of the Regional VAT Act</li>
                          <li>E2: Exempt under article 21 of the Regional VAT Act</li>
                          <li>E3: Exempt under article 22 of the Regional VAT Act</li>
                          <li>E4: Exempt under articles 23 and 24 of the Regional VAT Act</li>
                          <li>E5: Exempt under article 25 of the Regional VAT Act</li>
                          <li>E6: Exempt for other reasons</li>
                        </ol>
                    base_imponible:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Exempt tax base in euros corresponding to the cause of exemption.
                especial:
                  type: object
                  description: This section contains additional optional fields.
                  properties:
                    inversion_sujeto_pasivo:
                      type: boolean
                      default: false
                      description: With reverse charge.
                    retencion_soportada:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Withholding tax borne.
                    base_imponible_a_coste:
                      type: string
                      pattern: (\+|-)?\d{1,12}(\.\d{0,2})?
                      description: Tax base at cost (for VAT groups – advanced level).
                    clave_regimen:
                      type: string
                      default: "01"
                      enum:
                      - "01"
                      - "02"
                      - "03"
                      - "04"
                      - "05"
                      - "06"
                      - "07"
                      - "08"
                      - "09"
                      - "10"
                      - "11"
                      - "12"
                      - "13"
                      - "14"
                      - "15"
                      - "17"
                      - "19"
                      - "51"
                      - "52"
                      - "53"
                      - "54"
                      description: Special VAT regime key and operations with tax significance.
              example:
                accion: SUBSANAR
                serie: A
                numero: "234634"
                fecha_expedicion: CURRENT_DATE
                simplificada: false
                nif: A15022510
                nombre: Empresa de ejemplo SL
                direccion: direccion cliente
                cp: "48992"
                descripcion: descripcion de la factura
                tipo_operacion: servicios
                lineas:
                - descripcion: linea 1
                  cantidad: "2"
                  importe_unitario: "100.00"
                  importe_total: "242.00"
                desglose_iva:
                - base_imponible: "200.00"
                  tipo_impositivo: "21"
                  cuota_impuesto: "42"
                importe_total: "242.00"
      responses:
        "200":
          description: Invoice modified
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    description: Unique record identifier for querying its status.
                    type: string
                    example: ea6eae92-bac6-48c3-baa4-2bbf6b5ee562
                  tbai:
                    description: TicketBai code.
                    type: string
                    example: TBAI-B05434202-021224-mwUG7NRo2ZNxp-010
                  estado:
                    description: Record status. Will always be "Pendiente" (Pending) as a response to a creation. This status can be subsequently checked using the `/status` endpoint.
                    type: string
                    example: Pendiente
                  url:
                    description: QR code verification URL.
                    type: string
                    example: https://pruebas-ticketbai.araba.eus/tbai/qrtbai/?id=TBAI-B05434202-021224-mwUG7NRo2ZNxp-010&s=A&nf=234634&i=242&cr=010
                  qr:
                    description: Base 64 QR code containing the URL.
                    type: string
                    example: jBBWRw0KGgoABAANSUhEAH0CAIAAABE...
        "500":
          description: Server error
  /ticketbai/cancel:
    post:
      summary: Cancel Invoice
      description: |
        This endpoint allows cancelling existing invoices. When doing so, the new information is sent to the tax authority. Once an invoice is cancelled, a
        new one cannot be created with the same (`serie`, `numero`).

        &nbsp;

        This endpoint also accepts an optional `Idempotency-Key` header. If present, retries of the same logical request with the same key replay the original
        response (including the `Idempotent-Replayed: true` response header and the echoed `Idempotency-Key`).
        Keys are scoped per NIF and remembered for 24 hours.
        Reusing the same key with a different body returns 422; a concurrent retry while the first is still
        in flight returns 409.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/cancel' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data-raw '{
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/cancel'
          headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          }
          payload = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          }
          response = requests.post(url, headers=headers, json=payload)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/cancel';
          const headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          };
          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'serie': 'A',
            'numero': '234634',
            'fecha_expedicion': 'CURRENT_DATE'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/cancel", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/cancel";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
            "serie": "A",
            "numero": "234634",
            "fecha_expedicion": "CURRENT_DATE"
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n  \"serie\": \"A\",\n  \"numero\": \"234634\",\n  \"fecha_expedicion\": \"CURRENT_DATE\"\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/cancel\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                            "serie": "A",
                            "numero": "234634",
                            "fecha_expedicion": "CURRENT_DATE"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/cancel"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
            ""serie"": ""A"",
            ""numero"": ""234634"",
            ""fecha_expedicion"": ""CURRENT_DATE""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/cancel", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/cancel"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "  ""serie"": ""A""," & vbCrLf & _
                 "  ""numero"": ""234634""," & vbCrLf & _
                 "  ""fecha_expedicion"": ""CURRENT_DATE""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      parameters:
      - in: header
        name: Idempotency-Key
        required: false
        description: Optional unique key that guarantees retries of the same request don't create duplicates. Printable ASCII string, 1–255 characters. Remembered per NIF for 24 hours.
        schema:
          type: string
          pattern: '^[\x20-\x7E]{1,255}$'
          minLength: 1
          maxLength: 255
          example: 8e1b9c2a-3f4d-4a6b-9c2e-1d2f3e4a5b6c
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - serie
              - numero
              - fecha_expedicion
              properties:
                serie:
                  type: string
                  maxLength: 20
                  description: Invoice series.
                numero:
                  type: string
                  minLength: 1
                  maxLength: 20
                  pattern: (\s*[^\s]\s*)+
                  description: Invoice number.
                fecha_expedicion:
                  type: string
                  pattern: \d{2,2}-\d{2,2}-\d{4,4}
                  description: Invoice issue date. Cannot be a date later than the current date.
                rechazo_previo:
                  type: boolean
                  default: false
                  description: |
                    Parameter only available in Álava and Guipúzcoa indicating whether the invoice to be cancelled was previously rejected.
                    It is part of what is known as the ZUZENDU service.
              example:
                serie: A
                numero: "234634"
                fecha_expedicion: CURRENT_DATE
      responses:
        "200":
          description: Invoice cancelled
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid:
                    description: Unique record identifier for querying its status.
                    type: string
                    example: b018ced3-b362-4494-8776-9eefff1c160c
                  estado:
                    description: Record status.
                    type: string
                    example: Pendiente
              example:
                estado: Pendiente
                uuid: b018ced3-b362-4494-8776-9eefff1c160c
        "500":
          description: Server error
  /ticketbai/list:
    post:
      summary: List Invoices
      description: |
        The Basque Country tax authorities have not enabled an invoice query service via API, therefore,
        this endpoint allows querying invoices submitted to the corresponding tax authority as they are recorded in our system.
        A single record per invoice (`serie`, `numero` and `fecha_expedicion`) is returned with the latest status in our system.

        &nbsp;

        To obtain a complete list of issued invoices, you can visit the following URLs of the corresponding tax authority:

        <ul style="list-style: disc; margin-top: 6px;">
          <li><a href="https://ticketbai.araba.eus/tbai/consultafacturas/?idioma=es">Álava</a></li>
          <li><a href="https://www.gipuzkoa.eus/es/web/ogasuna/ticketbai/consulta-facturas">Guipuzcoa</a></li>
          <li><a href="https://www.batuz.eus/es/lroe">Vizcaya</a></li>
        </ul>

        In the test environment, invoice data will be stored for a maximum of 90 days.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/list' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data-raw '{
            "rango_fecha_expedicion": {
              "desde": "03-12-2024",
              "hasta": "25-12-2025"
            },
            "serie": "A"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/list'
          headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          }
          payload = {
            'rango_fecha_expedicion': {
              'desde': '03-12-2024',
              'hasta': '25-12-2025'
            },
            'serie': 'A'
          }
          response = requests.post(url, headers=headers, json=payload)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/list';
          const headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          };
          const data = {
            'rango_fecha_expedicion': {
              'desde': '03-12-2024',
              'hasta': '25-12-2025'
            },
            'serie': 'A'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'rango_fecha_expedicion': {
              'desde': '03-12-2024',
              'hasta': '25-12-2025'
            },
            'serie': 'A'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/list", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/list";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
            "rango_fecha_expedicion": {
              "desde": "03-12-2024",
              "hasta": "25-12-2025"
            },
            "serie": "A"
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n  \"rango_fecha_expedicion\": {\n    \"desde\": \"03-12-2024\",\n    \"hasta\": \"25-12-2025\"\n  },\n  \"serie\": \"A\"\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/list\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                            "rango_fecha_expedicion": {
                              "desde": "03-12-2024",
                              "hasta": "25-12-2025"
                            },
                            "serie": "A"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/list"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
            ""rango_fecha_expedicion"": {
              ""desde"": ""03-12-2024"",
              ""hasta"": ""25-12-2025""
            },
            ""serie"": ""A""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/list", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/list"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "  ""rango_fecha_expedicion"": {" & vbCrLf & _
                 "    ""desde"": ""03-12-2024""," & vbCrLf & _
                 "    ""hasta"": ""25-12-2025""" & vbCrLf & _
                 "  }," & vbCrLf & _
                 "  ""serie"": ""A""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      requestBody:
        content:
          application/json:
            schema:
              type: object
              example:
                rango_fecha_expedicion:
                  desde: 03-12-2024
                  hasta: 05-01-2025
                serie: A
              required:
              - rango_fecha_expedicion
              properties:
                rango_fecha_expedicion:
                  type: object
                  description: |
                    Date range of the invoice issue dates to query.
                  properties:
                    desde:
                      type: string
                      pattern: \d{2,2}-\d{2,2}-\d{4,4}
                      description: Start date of the invoice issue date range to query.
                    hasta:
                      type: string
                      pattern: \d{2,2}-\d{2,2}-\d{4,4}
                      description: |
                        End date of the invoice issue date range to query.
                        Must be greater than `desde`.
                serie:
                  type: string
                  maxLength: 20
                  description: Invoice series.
                pagina:
                  type: integer
                  description: This endpoint returns a maximum of 200 invoices per page.
                  default: 1
      responses:
        "200":
          description: Invoice list
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    nif:
                      description: Invoice issuer's NIF.
                      type: string
                      example: A15022510
                    serie:
                      description: Invoice series.
                      type: string
                      example: A
                    numero:
                      description: Número de la factura.
                      type: string
                      example: 234634
                    fecha_expedicion:
                      description: Invoice issue date.
                      type: string
                      example: CURRENT_DATE
                    estado:
                      description: |
                        Invoice status:
                        <ol style="list-style: disc;">
                          <li>Pendiente: Record queued and not yet processed.</li>
                          <li>Correcto: Record successfully processed by the corresponding tax authority.</li>
                          <li>Aceptado con errores: Record accepted with errors.</li>
                          <li>Incorrecto: Record considered incorrect.</li>
                          <li>Anulada: Cancellation record successfully processed by the corresponding tax authority.</li>
                        </ol>
                      type: string
                    json_req:
                      description: JSON sent to our API.
                    url:
                      description: QR code verification URL.
                      type: string
                    tbai:
                      description: TicketBai code.
                      type: string
                    mensaje_error:
                      description: Error description as reported by the corresponding tax authority.
                      type: string
                  example:
                    nif: A15022510
                    estado: Correcto
                    json_req: "{\"serie\": \"A\", \"numero\": \"234634\", \"fecha_expedicion\": \"CURRENT_DATE\", ... }"
                    url: https://pruebas-ticketbai.araba.eus/tbai/qrtbai/?id=TBAI-A15022510-021224-mwUG7NRo2ZNxp-010&s=A&nf=34547&i=242&cr=010
                    tbai: TBAI-B05434202-021224-mwUG7NRo2ZNxp-010
  /ticketbai/export:
    post:
      summary: Export XMLs
      description: |
        This endpoint allows exporting XML files in batches, both request and response, of invoices submitted to the tax authority.

        &nbsp;

        The way to download the files is by specifying the fiscal year and period in which those records were generated.
        Our API response consists of a list of URLs containing the invoice XML files. These URLs have an
        expiry of 15 minutes. Each call returns a maximum of 500 URLs and, if there are more, a pagination token is returned.
        This token must be used in the next call to obtain the remaining URLs.

        &nbsp;

        In the test environment, XMLs will be stored for a maximum of 90 days.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/export' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data-raw '{
            "ejercicio": '2024',
            "periodo": '12',
            "token": "CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...",
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/export'
          headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          }
          payload = {
            'ejercicio': '2024',
            'periodo': '12',
            'token': 'CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...'
          }
          response = requests.post(url, headers=headers, json=payload)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/export';
          const headers = {
            'Authorization': 'Bearer <API_KEY>',
            'Content-Type': 'application/json'
          };
          const data = {
            'ejercicio': 2024,
            'periodo': 12,
            'token': 'CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'ejercicio': 2024,
            'periodo': 12,
            'token': 'CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/export", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/export";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
            "ejercicio": '2024',
            "periodo": '12',
            "token": "CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...",
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n  \"ejercicio\": '2024',\n  \"periodo\": '12',\n  \"token\": \"CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...\",\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/export\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                            "ejercicio": '2024',
                            "periodo": '12',
                            "token": "CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...",
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/export"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
            ""ejercicio"": '2024',
            ""periodo"": '12',
            ""token"": ""CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD..."",
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/export", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/export"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "  ""ejercicio"": '2024'," & vbCrLf & _
                 "  ""periodo"": '12'," & vbCrLf & _
                 "  ""token"": ""CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...""," & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      requestBody:
        content:
          application/json:
            schema:
              type: object
              example:
                ejercicio: "2024"
                periodo: "12"
                token: CkJ0ZXN0L0I3NTc3Nzg0Ny8yMD...
              required:
              - ejercicio
              - periodo
              properties:
                ejercicio:
                  type: string
                  description: Fiscal year of the date on which the invoicing record was generated. It does not have to match the issue date or the operation date.
                periodo:
                  type: string
                  description: Period of the date on which the invoicing record was generated. It does not have to match the issue date or the operation date.
                token:
                  type: string
                  description: Pagination token.
      responses:
        "200":
          description: XML file list.
          content:
            application/json:
              schema:
                type: object
                properties:
                  urls:
                    type: array
                    description: |
                      Array with the URLs of the invoice XML files. These URLs expire after 15 minutes.
                    maxItems: 500
                    items:
                      type: string
                      format: uri
                      description: URL of the invoice XML files.
                    example:
                    - https://bucket/url_1_req.xml
                    - https://bucket/url_1_res.xml
                    - '...'
                  token:
                    type: string
                    description: Pagination token to get the next page.
                    example: BkJ1ZXH0L5I3HTc7Nzg0Ny8ynH...
  /ticketbai/downloadXML:
    post:
      summary: Download XML
      description: |
        This endpoint allows downloading the XML files of invoices submitted through TicketBai.
        &nbsp;

        The way to access the XML files is through the invoice series and number. Because it is possible that
        multiple different records exist for the same series and number (creation and cancellation, for example), the response
        is generally an array of XML files as shown in the example.

        &nbsp;

        In the test environment, XMLs will be stored for a maximum of 90 days.
      x-codeSamples:
      - lang: cURL
        label: cURL
        source: |
          curl --request POST 'https://api.verifacti.com/ticketbai/downloadXML' \
          --header 'Authorization: Bearer <API_KEY>' \
          --header 'Content-Type: application/json' \
          --data '{
              "serie": "A",
              "numero": "234634"
          }'
      - lang: Python
        label: Python
        source: |
          import requests
          url = 'https://api.verifacti.com/ticketbai/downloadXML'
          headers = {
            'Authorization': 'Bearer <API_KEY>'
          }
          data = {
            'serie': 'A',
            'numero': '234634'
          }
          response = requests.post(url, headers=headers, json=data)
      - lang: JavaScript
        label: JavaScript
        source: |
          const url = 'https://api.verifacti.com/ticketbai/downloadXML';
          const headers = {
            'Authorization': 'Bearer <API_KEY>'
          };
          const data = {
            'serie': 'A',
            'numero': '234634'
          };
          fetch(url, { headers, method: 'POST', body: JSON.stringify(data) })
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error(error));
      - lang: Node.js
        label: Node.js
        source: |-
          const axios = require("axios");

          const data = {
            'serie': 'A',
            'numero': '234634'
          };

          const response = await axios.post("https://api.verifacti.com/ticketbai/downloadXML", data, {
            headers: {
              "Authorization": "Bearer <API_KEY>",
              "Content-Type": "application/json"
            }
          });

          console.log(response.data);
      - lang: PHP
        label: PHP
        source: |-
          <?php

          $url = "https://api.verifacti.com/ticketbai/downloadXML";

          $headers = [
              "Authorization: Bearer <API_KEY>",
              "Content-Type: application/json"
          ];

          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

          $body = <<<'JSON'
          {
              "serie": "A",
              "numero": "234634"
          }
          JSON;

          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          echo "HTTP Status: " . $httpCode . "\n";
          echo $response;
      - lang: Go
        label: Go
        source: "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := `\n{\n    \"serie\": \"A\",\n    \"numero\": \"234634\"\n}\n`\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.verifacti.com/ticketbai/downloadXML\", strings.NewReader(body))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treq.Header.Set(\"Authorization\", \"Bearer <API_KEY>\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tfmt.Println(\"Status:\", resp.StatusCode)\n\tfmt.Println(string(respBody))\n}"
      - lang: Java
        label: Java
        source: |-
          import java.net.URI;
          import java.net.http.HttpClient;
          import java.net.http.HttpRequest;
          import java.net.http.HttpResponse;

          public class Main {
              public static void main(String[] args) throws Exception {
                  HttpClient client = HttpClient.newHttpClient();

                  String body = """
                          {
                              "serie": "A",
                              "numero": "234634"
                          }
                          """;

                  HttpRequest request = HttpRequest.newBuilder()
                      .uri(URI.create("https://api.verifacti.com/ticketbai/downloadXML"))
                      .header("Authorization", "Bearer <API_KEY>")
                      .header("Content-Type", "application/json")
                      .POST(HttpRequest.BodyPublishers.ofString(body))
                      .build();

                  HttpResponse<String> response = client.send(request,
                      HttpResponse.BodyHandlers.ofString());

                  System.out.println(response.statusCode());
                  System.out.println(response.body());
              }
          }
      - lang: C#
        label: C#
        source: |-
          using System;
          using System.Net.Http;
          using System.Text;
          using System.Threading.Tasks;

          class Program
          {
              static async Task Main()
              {
                  using var client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Authorization", "Bearer <API_KEY>");

                  var body = @"
                      {
              ""serie"": ""A"",
              ""numero"": ""234634""
          }
                  ";

                  var content = new StringContent(body, Encoding.UTF8, "application/json");

                  var response = await client.PostAsync("https://api.verifacti.com/ticketbai/downloadXML", content);

                  var responseBody = await response.Content.ReadAsStringAsync();
                  Console.WriteLine($"Status: {response.StatusCode}");
                  Console.WriteLine(responseBody);
              }
          }
      - lang: VB6
        label: VB6
        source: |-
          Dim oHttp As Object
          Dim sUrl As String
          Dim sResponse As String

          Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")

          sUrl = "https://api.verifacti.com/ticketbai/downloadXML"

          oHttp.Open "POST", sUrl, False
          oHttp.setRequestHeader "Authorization", "Bearer <API_KEY>"
          oHttp.setRequestHeader "Content-Type", "application/json"

          Dim sBody As String
          sBody = "{" & vbCrLf & _
                 "    ""serie"": ""A""," & vbCrLf & _
                 "    ""numero"": ""234634""" & vbCrLf & _
                 "}"

          oHttp.send sBody

          sResponse = oHttp.responseText
          Debug.Print "Status: " & oHttp.Status
          Debug.Print sResponse

          Set oHttp = Nothing
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - serie
              - numero
              properties:
                serie:
                  type: string
                  example: A
                  maxLength: 20
                  description: Invoice series.
                numero:
                  type: string
                  minLength: 1
                  maxLength: 20
                  pattern: (\s*[^\s]\s*)+
                  example: "234634"
                  description: Invoice number.
      responses:
        "200":
          description: XML files
          content:
            application/json:
              schema:
                type: array
                items:
                  properties:
                    uuid:
                      description: Unique record identifier.
                      type: string
                    operacion:
                      description: Operation type.
                      type: string
                    xml_req:
                      description: Request XML file sent to the corresponding tax authority.
                      type: string
                    xml_res:
                      description: Response XML file from the corresponding tax authority.
                      type: string
                example:
                - uuid: b018ced3-b362-4494-8776-9eefff1c160c
                  operacion: Alta
                  xml_req: <?xml version="1.0" encoding="UTF-8"?><T:TicketBai ...
                  xml_res: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:TicketBaiResponse ...
          example:
        "500":
          description: Server error
components:
  schemas:
    estadoFactura:
      type: object
      properties:
        nif:
          description: Invoice issuer's NIF.
          type: string
          example: A15022510
        estado:
          description: |
            Invoice status:
            <ol style="list-style: disc;">
              <li>Pendiente: Record queued and not yet processed.</li>
              <li>Correcto: Record successfully processed by the corresponding tax authority.</li>
              <li>Aceptado con errores: Record accepted with errors.</li>
              <li>Incorrecto: Record considered incorrect.</li>
              <li>Anulada: Cancellation record successfully processed by the corresponding tax authority.</li>
            </ol>
          type: string
        json_req:
          description: JSON sent to our API.
        url:
          description: QR code verification URL.
          type: string
        tbai:
          description: TicketBai code.
          type: string
        mensaje_error:
          description: Error description as reported by the corresponding tax authority.
          type: string
      example:
        nif: A15022510
        estado: Correcto
        json_req: "{\"serie\": \"A\", \"numero\": \"234634\", \"fecha_expedicion\": \"CURRENT_DATE\", ... }"
        url: https://pruebas-ticketbai.araba.eus/tbai/qrtbai/?id=TBAI-A15022510-021224-mwUG7NRo2ZNxp-010&s=A&nf=34547&i=242&cr=010
        tbai: TBAI-B05434202-021224-mwUG7NRo2ZNxp-010
