# Lotes de facturas

> Timbre hasta 1,000 facturas de un emisor con una sola solicitud, revisadas todas antes de empezar.

Un lote sirve para lo que se factura de golpe: las cuotas del mes de un condominio, las colegiaturas, las ventas del día de un marketplace. En lugar de mil solicitudes y sus límites, manda una.

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/invoice_batches \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Idempotency-Key: cuotas-2026-10" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cuotas de octubre",
    "invoices": [
      {
        "reference": "depto-101",
        "customer": "cus_OufpKqnrvx9p1",
        "payment_form": "03",
        "items": [{ "product": "prd_OufpKqnrvx9p1" }]
      },
      {
        "reference": "depto-102",
        "customer": { "tax_id": "ICV060329BY0", "legal_name": "INMOBILIARIA CVA", "tax_system": "601", "zip": "33826" },
        "payment_form": "03",
        "items": [{ "description": "Cuota de mantenimiento", "product_key": "80131500", "unit_price": 1500 }]
      }
    ]
  }'
```

```ts tab="TypeScript"
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const invoiceBatch = await fiscalisto.invoiceBatches.create({
  name: "Cuotas de octubre",
  invoices: [
    {
      reference: "depto-101",
      customer: "cus_OufpKqnrvx9p1",
      payment_form: "03",
      items: [{ product: "prd_OufpKqnrvx9p1" }],
    },
    {
      reference: "depto-102",
      customer: {
        tax_id: "ICV060329BY0",
        legal_name: "INMOBILIARIA CVA",
        tax_system: "601",
        zip: "33826",
      },
      payment_form: "03",
      items: [
        {
          description: "Cuota de mantenimiento",
          product_key: "80131500",
          unit_price: 1500,
        },
      ],
    },
  ],
}, { idempotencyKey: "cuotas-2026-10" });
```

```python tab="Python"
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

invoice_batch = fiscalisto.invoice_batches.create({
    "name": "Cuotas de octubre",
    "invoices": [
        {
            "reference": "depto-101",
            "customer": "cus_OufpKqnrvx9p1",
            "payment_form": "03",
            "items": [{"product": "prd_OufpKqnrvx9p1"}],
        },
        {
            "reference": "depto-102",
            "customer": {
                "tax_id": "ICV060329BY0",
                "legal_name": "INMOBILIARIA CVA",
                "tax_system": "601",
                "zip": "33826",
            },
            "payment_form": "03",
            "items": [
                {
                    "description": "Cuota de mantenimiento",
                    "product_key": "80131500",
                    "unit_price": 1500,
                },
            ],
        },
    ],
}, idempotency_key="cuotas-2026-10")
```

```php tab="PHP"
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$invoiceBatch = $fiscalisto->invoiceBatches->create([
    'name' => 'Cuotas de octubre',
    'invoices' => [
        [
            'reference' => 'depto-101',
            'customer' => 'cus_OufpKqnrvx9p1',
            'payment_form' => '03',
            'items' => [['product' => 'prd_OufpKqnrvx9p1']],
        ],
        [
            'reference' => 'depto-102',
            'customer' => [
                'tax_id' => 'ICV060329BY0',
                'legal_name' => 'INMOBILIARIA CVA',
                'tax_system' => '601',
                'zip' => '33826',
            ],
            'payment_form' => '03',
            'items' => [
                [
                    'description' => 'Cuota de mantenimiento',
                    'product_key' => '80131500',
                    'unit_price' => 1500,
                ],
            ],
        ],
    ],
], ['idempotency_key' => 'cuotas-2026-10']);
```

```go tab="Go"
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	invoiceBatch, err := client.InvoiceBatches.Create(ctx, &fiscalisto.CreateInvoiceBatchParams{
		Name: fiscalisto.String("Cuotas de octubre"),
		Invoices: []fiscalisto.CreateInvoiceBatchParamsInvoice{
			{
				Reference:   fiscalisto.String("depto-101"),
				Customer:    fiscalisto.IDOf[fiscalisto.InvoiceCreateCustomer]("cus_OufpKqnrvx9p1"),
				PaymentForm: fiscalisto.String("03"),
				Items: []fiscalisto.InvoiceCreateItem{
					{Product: fiscalisto.String("prd_OufpKqnrvx9p1")},
				},
			},
			{
				Reference: fiscalisto.String("depto-102"),
				Customer: fiscalisto.ObjectOf(fiscalisto.InvoiceCreateCustomer{
					TaxID:     "ICV060329BY0",
					LegalName: "INMOBILIARIA CVA",
					TaxSystem: "601",
					Zip:       "33826",
				}),
				PaymentForm: fiscalisto.String("03"),
				Items: []fiscalisto.InvoiceCreateItem{
					{
						Description: fiscalisto.String("Cuota de mantenimiento"),
						ProductKey:  fiscalisto.String("80131500"),
						UnitPrice:   fiscalisto.Float64(1500),
					},
				},
			},
		},
	}, fiscalisto.WithIdempotencyKey("cuotas-2026-10"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(invoiceBatch.ID)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.CreateInvoiceBatchParams;
import com.fiscalisto.model.CreateInvoiceBatchParamsInvoice;
import com.fiscalisto.model.InvoiceCreateCustomer;
import com.fiscalisto.model.InvoiceCreateItem;
import java.util.List;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var invoiceBatch = fiscalisto.invoiceBatches().create(new CreateInvoiceBatchParams()
        .setName("Cuotas de octubre")
        .setInvoices(List.of(
                new CreateInvoiceBatchParamsInvoice()
                        .setReference("depto-101")
                        .setCustomer("cus_OufpKqnrvx9p1")
                        .setPaymentForm("03")
                        .setItems(List.of(
                                new InvoiceCreateItem()
                                        .setProduct("prd_OufpKqnrvx9p1")
                        )),
                new CreateInvoiceBatchParamsInvoice()
                        .setReference("depto-102")
                        .setCustomer(new InvoiceCreateCustomer()
                                .setTaxId("ICV060329BY0")
                                .setLegalName("INMOBILIARIA CVA")
                                .setTaxSystem("601")
                                .setZip("33826"))
                        .setPaymentForm("03")
                        .setItems(List.of(
                                new InvoiceCreateItem()
                                        .setDescription("Cuota de mantenimiento")
                                        .setProductKey("80131500")
                                        .setUnitPrice(1500)
                        ))
        )), RequestOptions.idempotencyKey("cuotas-2026-10"));
System.out.println(invoiceBatch.getId());
```

```csharp tab="C#"
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var invoiceBatch = await fiscalisto.InvoiceBatches.CreateAsync(new CreateInvoiceBatchParams
{
    Name = "Cuotas de octubre",
    Invoices = new()
    {
        new()
        {
            Reference = "depto-101",
            Customer = "cus_OufpKqnrvx9p1",
            PaymentForm = "03",
            Items = new()
            {
                new() { Product = "prd_OufpKqnrvx9p1" },
            },
        },
        new()
        {
            Reference = "depto-102",
            Customer = new InvoiceCreateCustomer
            {
                TaxId = "ICV060329BY0",
                LegalName = "INMOBILIARIA CVA",
                TaxSystem = "601",
                Zip = "33826",
            },
            PaymentForm = "03",
            Items = new()
            {
                new()
                {
                    Description = "Cuota de mantenimiento",
                    ProductKey = "80131500",
                    UnitPrice = 1500,
                },
            },
        },
    },
}, new RequestOptions { IdempotencyKey = "cuotas-2026-10" });
```

Cada factura del lote es el mismo cuerpo de [`POST /v1/invoices`](https://fiscalisto.com/docs/api/referencia/facturas/create-invoice), sin `issuer` (el lote es de un emisor), sin `type` ni `global` (son facturas de ingreso) y con `reference` en lugar de `metadata`: su identificador de esa factura, que vuelve en el resultado.

## Cómo se timbra

1. **Se revisan todas antes de empezar.** Si una no pasa la revisión, la API responde `422` `batch_invalid` con `param` en la factura y el campo (`invoices.3.items.0.unit_price`) y no se timbra ninguna. Corríjala y mande el lote otra vez.
2. **Se responde `202` de inmediato**, con el lote en `status: "processing"`.
3. **Se timbran en segundo plano**, a la velocidad que permite el PAC. Cada factura timbrada manda su `invoice.stamped`, como cualquier otra.
4. **Al terminar** llega `invoice_batch.completed` y el lote queda `completed`, con cuántas se timbraron (`stamped`) y cuántas no (`failed`).

```json
{
  "id": "bat_OufpKqnrvx9p4hMdcoapAo5aaGJEme7mXj",
  "object": "invoice_batch",
  "status": "completed",
  "total": 2,
  "stamped": 1,
  "failed": 1,
  "processing": 0,
  "invoices": [
    { "index": 0, "reference": "depto-101", "status": "valid", "invoice": "inv_OufpKqnrvx9p0mn7VjQ6JlfipKAkHWstOK", "uuid": "DB494B07-D6DE-4F70-8ED0-C8B864FF8717", "total": 1740, "error": null },
    { "index": 1, "reference": "depto-102", "status": "failed", "invoice": null, "uuid": null, "total": 1740, "error": "El SAT no reconoce el nombre del cliente. Escríbalo exactamente como en su constancia de situación fiscal, en mayúsculas y sin «S.A. de C.V.» ni otro régimen de capital." }
  ]
}
```

Una factura puede fallar aunque pasó la revisión, si el SAT la rechaza (casi siempre por los datos del cliente). Esas no usan timbre: corríjalas y timbre cada una con `POST /v1/invoices`.

## Consultar el avance

[`GET /v1/invoice_batches/{id}`](https://fiscalisto.com/docs/api/referencia/lotes/get-invoice-batch) dice cuántas van y el estado de cada una. Si no usa webhooks, consúltelo cada pocos segundos hasta que diga `completed`.

## Timbres

Cada factura timbrada usa un timbre, al timbrarse. Antes de mandar un lote grande revise que le alcancen con [`GET /v1/balance`](https://fiscalisto.com/docs/api/referencia/cuenta/get-balance): si se acaban a la mitad, las que faltan quedan `failed` con el motivo en `error`. Después de comprar, mándelas en otro lote, con otra `Idempotency-Key`.

## Repetirlo

Mandar el mismo lote con la misma `Idempotency-Key` contesta el lote que ya existe (`202`, como la primera vez, con `idempotent-replayed: true`), sin timbrar nada otra vez.
