# API de facturación

> Timbre CFDI 4.0 desde su sistema con una sola llamada: facturas, pagos, notas de crédito, nómina y retenciones, con las revisiones del SAT de Fiscalisto.

La API de Fiscalisto timbra comprobantes fiscales (CFDI 4.0) desde su servidor. Usted manda los datos de la factura en JSON; Fiscalisto llena lo que tiene un valor usual, revisa las reglas del SAT antes de gastar un timbre, la sella con el certificado del emisor, la timbra con el PAC y le contesta con la factura timbrada, su UUID, el PDF y el XML.

Los nombres de la API están en inglés, como en cualquier API (`customer`, `items`, `unit_price`); los textos, los errores y estas guías están en español.

## Su primera factura en un minuto

1. Abra una cuenta API en Fiscalisto (selector de empresa › **Nueva cuenta API**). Al crearla le damos una llave de pruebas que empieza con `fk_test_` y un emisor de pruebas listo para timbrar.
2. Guarde la llave en una variable de entorno de su servidor:

```bash
export FISCALISTO_API_KEY="fk_test_..."
```

3. Timbre una factura:

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/invoices \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Idempotency-Key: pedido-A-1042" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": {
      "tax_id": "ICV060329BY0",
      "legal_name": "INMOBILIARIA CVA",
      "tax_system": "601",
      "zip": "33826"
    },
    "payment_form": "03",
    "items": [
      { "description": "Mensualidad", "product_key": "86121700", "quantity": 2, "unit_price": 2500 }
    ]
  }'
```

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

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

const invoice = await fiscalisto.invoices.create({
  customer: {
    tax_id: "ICV060329BY0",
    legal_name: "INMOBILIARIA CVA",
    tax_system: "601",
    zip: "33826",
  },
  payment_form: "03",
  items: [
    {
      description: "Mensualidad",
      product_key: "86121700",
      quantity: 2,
      unit_price: 2500,
    },
  ],
}, { idempotencyKey: "pedido-A-1042" });
```

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

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

invoice = fiscalisto.invoices.create({
    "customer": {
        "tax_id": "ICV060329BY0",
        "legal_name": "INMOBILIARIA CVA",
        "tax_system": "601",
        "zip": "33826",
    },
    "payment_form": "03",
    "items": [
        {
            "description": "Mensualidad",
            "product_key": "86121700",
            "quantity": 2,
            "unit_price": 2500,
        },
    ],
}, idempotency_key="pedido-A-1042")
```

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

use Fiscalisto\Fiscalisto;

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

$invoice = $fiscalisto->invoices->create([
    'customer' => [
        'tax_id' => 'ICV060329BY0',
        'legal_name' => 'INMOBILIARIA CVA',
        'tax_system' => '601',
        'zip' => '33826',
    ],
    'payment_form' => '03',
    'items' => [
        [
            'description' => 'Mensualidad',
            'product_key' => '86121700',
            'quantity' => 2,
            'unit_price' => 2500,
        ],
    ],
], ['idempotency_key' => 'pedido-A-1042']);
```

```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()

	invoice, err := client.Invoices.Create(ctx, &fiscalisto.InvoiceCreate{
		Customer: fiscalisto.ObjectOf(fiscalisto.InvoiceCreateCustomer{
			TaxID:     "ICV060329BY0",
			LegalName: "INMOBILIARIA CVA",
			TaxSystem: "601",
			Zip:       "33826",
		}),
		PaymentForm: fiscalisto.String("03"),
		Items: []fiscalisto.InvoiceCreateItem{
			{
				Description: fiscalisto.String("Mensualidad"),
				ProductKey:  fiscalisto.String("86121700"),
				Quantity:    fiscalisto.Float64(2),
				UnitPrice:   fiscalisto.Float64(2500),
			},
		},
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(invoice.ID)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.InvoiceCreate;
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 invoice = fiscalisto.invoices().create(new InvoiceCreate()
        .setCustomer(new InvoiceCreateCustomer()
                .setTaxId("ICV060329BY0")
                .setLegalName("INMOBILIARIA CVA")
                .setTaxSystem("601")
                .setZip("33826"))
        .setPaymentForm("03")
        .setItems(List.of(
                new InvoiceCreateItem()
                        .setDescription("Mensualidad")
                        .setProductKey("86121700")
                        .setQuantity(2)
                        .setUnitPrice(2500)
        )), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(invoice.getId());
```

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

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

var invoice = await fiscalisto.Invoices.CreateAsync(new InvoiceCreate
{
    Customer = new InvoiceCreateCustomer
    {
        TaxId = "ICV060329BY0",
        LegalName = "INMOBILIARIA CVA",
        TaxSystem = "601",
        Zip = "33826",
    },
    PaymentForm = "03",
    Items = new()
    {
        new()
        {
            Description = "Mensualidad",
            ProductKey = "86121700",
            Quantity = 2,
            UnitPrice = 2500,
        },
    },
}, new RequestOptions { IdempotencyKey = "pedido-A-1042" });
```

La respuesta es la factura timbrada (`201`):

```json
{
  "id": "inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg",
  "object": "invoice",
  "livemode": false,
  "status": "valid",
  "uuid": "5F1E8C2A-3B7D-4C9E-A1B2-C3D4E5F60718",
  "folio": "1",
  "subtotal": 5000,
  "taxes": { "iva": 800, "ieps": 0, "iva_withheld": 0, "isr_withheld": 0, "local_transferred": 0, "local_withheld": 0 },
  "total": 5800,
  "...": "..."
}
```

4. Descargue el PDF o el XML:

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/invoices/inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg/pdf \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" -o factura.pdf
```

```ts tab="TypeScript"
import { writeFile } from "node:fs/promises";
import { Fiscalisto } from "fiscalisto";

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

await writeFile("factura.pdf", await fiscalisto.invoices.pdf("inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg"));
```

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

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

with open("factura.pdf", "wb") as f:
    f.write(fiscalisto.invoices.pdf("inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg"))
```

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

use Fiscalisto\Fiscalisto;

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

file_put_contents('factura.pdf', $fiscalisto->invoices->pdf('inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg'));
```

```go tab="Go"
package main

import (
	"context"
	"log"
	"os"

	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()

	pdf, err := client.Invoices.PDF(ctx, "inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg", nil)
	if err != nil {
		log.Fatal(err)
	}
	if err := os.WriteFile("factura.pdf", pdf, 0o644); err != nil {
		log.Fatal(err)
	}
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import java.nio.file.Files;
import java.nio.file.Path;

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

Files.write(Path.of("factura.pdf"), fiscalisto.invoices().pdf("inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg"));
```

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

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

await File.WriteAllBytesAsync("factura.pdf", await fiscalisto.Invoices.PdfAsync("inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg"));
```

No mandó el uso del CFDI, el método de pago, la moneda, la unidad, el objeto de impuesto ni el IVA: tienen su valor usual (uso G03, PUE, MXN, unidad E48, objeto 02, IVA 16%). Mande solo lo que cambia.

Con TypeScript, Python, PHP, Go, Java o C#, los [SDKs](https://fiscalisto.com/docs/api/sdk) le dan tipos para cada campo y la `Idempotency-Key` sin pensarlo:

```ts
import { Fiscalisto } from "fiscalisto";

const fiscalisto = new Fiscalisto(process.env.FISCALISTO_API_KEY);
const invoice = await fiscalisto.invoices.create({ customer, payment_form: "03", items });
```

## Lo que necesita saber

- **Pruebas y producción.** Las llaves `fk_test_` timbran gratis en el ambiente de pruebas del SAT; las `fk_live_` timbran CFDI reales y usan un timbre cada una. Vea [Pruebas y producción](https://fiscalisto.com/docs/api/pruebas-y-produccion).
- **Idempotency-Key.** Todo lo que timbra la pide. Si la respuesta se pierde, repita la solicitud con la misma: nunca se timbra dos veces. Vea [Idempotencia](https://fiscalisto.com/docs/api/idempotencia).
- **Errores claros.** Cada error dice qué campo corregir (`param`), cómo (`message`) y, si el SAT lo rechazó, su código (`sat_code`). Vea [Errores](https://fiscalisto.com/docs/api/errores).
- **Webhooks.** Las cancelaciones que el cliente acepta días después, las facturas que el PAC tardó en timbrar y los lotes le llegan como eventos firmados. Vea [Webhooks](https://fiscalisto.com/docs/api/webhooks).

## Qué puede timbrar

| Comprobante | Ruta |
| --- | --- |
| Factura de ingreso, global o de traslado (con complementos) | [`POST /v1/invoices`](https://fiscalisto.com/docs/api/referencia/facturas/create-invoice) |
| Complemento de pago (tipo P) | [`POST /v1/payments`](https://fiscalisto.com/docs/api/referencia/pagos-y-notas-de-credito/create-payment) |
| Nota de crédito (tipo E) | [`POST /v1/credit_notes`](https://fiscalisto.com/docs/api/referencia/pagos-y-notas-de-credito/create-credit-note) |
| Anticipo y su aplicación | [`POST /v1/advances`](https://fiscalisto.com/docs/api/referencia/anticipos/create-advance) |
| Recibo de nómina (tipo N) | [`POST /v1/payroll_receipts`](https://fiscalisto.com/docs/api/referencia/nomina/create-payroll-receipt) |
| Constancia de retenciones | [`POST /v1/retentions`](https://fiscalisto.com/docs/api/referencia/retenciones/create-retention) |
| Hasta 1,000 facturas de una vez | [`POST /v1/invoice_batches`](https://fiscalisto.com/docs/api/referencia/lotes/create-invoice-batch) |

## Para agentes y herramientas

- Para que un agente de código (Claude Code, Cursor, Codex…) integre Fiscalisto, conecte el servidor MCP de esta documentación y dele la guía en una página: vea [Fiscalisto para agentes de IA](https://fiscalisto.com/docs/api/agentes).
- El documento OpenAPI 3.1 completo está en [`https://api.fiscalisto.com/v1/openapi.json`](https://api.fiscalisto.com/v1/openapi.json), sin llave. Cada campo tiene su descripción y su nombre en el XML del SAT.
- Cada página de estas guías existe también en Markdown: agregue `.md` a su dirección (por ejemplo [`/docs/api/idempotencia.md`](https://fiscalisto.com/docs/api/idempotencia.md)).
- [`/docs/api/llms.txt`](https://fiscalisto.com/docs/api/llms.txt) es el índice de todas las páginas, y [`/docs/api/llms-full.txt`](https://fiscalisto.com/docs/api/llms-full.txt) las guías completas en un solo archivo.
