# Pedirle al SAT las facturas de un emisor

`POST https://api.fiscalisto.com/v1/sat_downloads`

La descarga masiva del SAT: las facturas que el emisor recibió (o emitió) en un periodo de hasta un año, con su XML. Contesta 202 de inmediato; el SAT tarda de minutos a horas y al terminar llega sat_download.completed (o sat_download.failed) y las facturas quedan en GET /v1/sat_invoices. En producción necesita la e.firma guardada del emisor; en pruebas no se le pregunta al SAT: la descarga trae facturas de ejemplo al instante. En producción usa 1 timbre por cada 100 CFDI que trae (al menos 1).

## Parámetros

| Nombre | Dónde | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `Idempotency-Key` | encabezado |  | Opcional (los SDK la mandan solos). Si la respuesta se pierde, repita la solicitud con el mismo valor durante 24 horas: contesta lo mismo, con idempotent-replayed: true, y no lo hace dos veces (ni crea, ni manda correos, ni cobra). |

## Cuerpo

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `issuer` | string |  | El emisor (iss_…). Por omisión, su único emisor. |
| `direction` | `received`, `issued` |  | received (las facturas que le hicieron al emisor, por omisión) o issued (las que emitió, aunque no haya sido con Fiscalisto). (por omisión "received") |
| `from` | string | sí | Desde qué día (incluido), en hora de la Ciudad de México. |
| `to` | string | sí | Hasta qué día (incluido). A lo más un año después de from, y no después de hoy. |
| `type` | `I`, `E`, `P`, `T`, `N` |  | Solo un tipo de comprobante: I, E, P, T o N. Por omisión, todos. |
| `counterparty_tax_id` | string |  | Solo las de un RFC: el emisor de las recibidas, o el receptor de las emitidas. |
| `uuid` | string (uuid) |  | Una sola factura, por su folio fiscal (UUID). |

Ejemplo:

```json
{
  "direction": "received",
  "from": "2026-09-01",
  "to": "2026-09-30"
}
```

## Con el SDK de TypeScript

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

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

const satDownload = await fiscalisto.satDownloads.create({
  direction: "received",
  from: "2026-09-01",
  to: "2026-09-30",
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

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

sat_download = fiscalisto.sat_downloads.create({
    "direction": "received",
    "from": "2026-09-01",
    "to": "2026-09-30",
}, idempotency_key="pedido-A-1042")
```

## Con el SDK de PHP

```php
<?php

use Fiscalisto\Fiscalisto;

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

$satDownload = $fiscalisto->satDownloads->create([
    'direction' => 'received',
    'from' => '2026-09-01',
    'to' => '2026-09-30',
], ['idempotency_key' => 'pedido-A-1042']);
```

## Con el SDK de .NET

```csharp
using Fiscalisto;

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

var satDownload = await fiscalisto.SatDownloads.CreateAsync(new CreateSatDownloadParams
{
    Direction = "received",
    From = "2026-09-01",
    To = "2026-09-30",
}, new RequestOptions { IdempotencyKey = "pedido-A-1042" });
```

## Con el SDK de Go

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

	satDownload, err := client.SatDownloads.Create(ctx, &fiscalisto.CreateSatDownloadParams{
		Direction: fiscalisto.String("received"),
		From:      "2026-09-01",
		To:        "2026-09-30",
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(satDownload.ID)
}
```

## Con el SDK de Java

```java
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.CreateSatDownloadParams;

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

var satDownload = fiscalisto.satDownloads().create(new CreateSatDownloadParams()
        .setDirection("received")
        .setFrom("2026-09-01")
        .setTo("2026-09-30"), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(satDownload.getId());
```

## Respuesta 202

Correcto.

Un objeto `SatDownload`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `id` | string | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `livemode` | boolean | sí | true en producción (llaves fk_live_), false en pruebas (fk_test_). Lo de pruebas no vale ante el SAT. |
| `object` | `"sat_download"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor cuyas facturas se piden. |
| `direction` | `received`, `issued` | sí | received (las que le hicieron) o issued (las que emitió). |
| `from` | string o null | sí | Desde qué día (incluido). |
| `to` | string o null | sí | Hasta qué día (incluido). |
| `type` | `I`, `E`, `P`, `T`, `N` o null | sí | El tipo de comprobante pedido, o null si todos. |
| `counterparty_tax_id` | string o null | sí | El RFC de la contraparte pedido, o null. |
| `uuid` | string o null | sí | El folio fiscal pedido, o null. |
| `status` | `processing`, `completed`, `failed` | sí | processing (el SAT la está preparando: de minutos a horas), completed (las facturas ya están en GET /v1/sat_invoices) o failed (el motivo en error). |
| `new_invoices` | integer o null | sí | Cuántas facturas nuevas trajo (las que ya tenía no cuentan). null mientras no termine. |
| `error` | string o null | sí | Por qué falló, como lo dijo el SAT. null si no falló. |
| `created_at` | string (date-time) o null | sí | Cuándo se pidió. |
| `completed_at` | string (date-time) o null | sí | Cuándo terminó, o null. |

```json
{
  "id": "sdl_OufpKqnrvx9p3n8vQd2LkW7mZr1XyT5uBc",
  "object": "sat_download",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "direction": "received",
  "from": "2026-09-01",
  "to": "2026-09-30",
  "type": null,
  "counterparty_tax_id": null,
  "uuid": null,
  "status": "completed",
  "new_invoices": 8,
  "error": null,
  "created_at": "2026-10-24T10:20:00-06:00",
  "completed_at": "2026-10-24T10:27:41-06:00"
}
```

## Errores

Puede responder 400, 401, 403, 404, 429, 500 con el cuerpo de error de siempre; cada código está en https://fiscalisto.com/docs/api/errores.md.
