# Declaraciones del SAT

> Las declaraciones que un emisor presentó ante el SAT, con su PDF, su acuse y sus cifras: provisionales, la anual de persona moral y las del servicio anterior Declaraciones y pagos.

Con la e.firma del emisor usted trae del SAT todas las declaraciones que presentó: las **provisionales o definitivas** de cada mes (desde 2022), la **anual** de persona moral (desde 2019) y las del servicio anterior **Declaraciones y pagos** (2021 y antes). Cada una llega con su PDF, su acuse, el número de operación, la línea de captura y sus cifras por impuesto, incluido el **coeficiente de utilidad** que aplicó. Sirve para revisar lo que ya se pagó, armar la contabilidad o calcular el siguiente pago provisional con el coeficiente del SAT.

Solo se consulta: nunca se presenta, firma ni cambia nada en el SAT.

## Lo que cuesta

| Qué | En producción | En pruebas |
| --- | --- | --- |
| Consultar al SAT (`POST /v1/sat_declarations/refresh`) | 1 timbre por consulta | Gratis |
| Listar, ver y descargar lo que ya trajo | Gratis | Gratis |

Si el SAT no contesta o no deja entrar con la e.firma, el timbre regresa. Cada emisor se puede consultar una vez cada 10 minutos (cada consulta es una entrada al SAT con su e.firma); antes, la API contesta `429` `sat_refresh_too_soon` con `Retry-After`. Fiscalisto no consulta solo: las declaraciones se actualizan cuando usted lo pide.

## En pruebas y en producción

- **En producción** se entra al SAT con la e.firma que el emisor guardó con `keep_for_downloads: true`, la misma de las [descargas del SAT](https://fiscalisto.com/docs/api/descargas-del-sat#guardar-la-efirma-del-emisor).
- **En pruebas** el SAT no tiene un ambiente de pruebas, así que no se le pregunta: la consulta trae al instante las declaraciones de ejemplo de este año (hasta el mes pasado) y la anual del año anterior, con su PDF y su acuse. No necesita e.firma.

## Consultar al SAT

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/sat_declarations/refresh \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "issuer": "iss_OufpKqnrvx9p" }'
```

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

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

const satDeclarationsRefresh = await fiscalisto.satDeclarations.refresh({ issuer: "iss_OufpKqnrvx9p" });
```

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

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

sat_declarations_refresh = fiscalisto.sat_declarations.refresh({"issuer": "iss_OufpKqnrvx9p"})
```

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

use Fiscalisto\Fiscalisto;

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

$satDeclarationsRefresh = $fiscalisto->satDeclarations->refresh(['issuer' => 'iss_OufpKqnrvx9p']);
```

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

	satDeclarationsRefresh, err := client.SatDeclarations.Refresh(ctx, &fiscalisto.RefreshSatDeclarationsParams{
		Issuer: fiscalisto.String("iss_OufpKqnrvx9p"),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *satDeclarationsRefresh)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.model.RefreshSatDeclarationsParams;

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

var satDeclarationsRefresh = fiscalisto.satDeclarations().refresh(new RefreshSatDeclarationsParams().setIssuer("iss_OufpKqnrvx9p"));
System.out.println(satDeclarationsRefresh);
```

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

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

var satDeclarationsRefresh = await fiscalisto.SatDeclarations.RefreshAsync(new RefreshSatDeclarationsParams
{
    Issuer = "iss_OufpKqnrvx9p",
});
```

La primera consulta trae todos los años que el SAT conserva; las siguientes, este año y el anterior, y vuelven a pedir los archivos que el SAT no pudo dar. La respuesta dice cuántas encontró (`found`) y cuántos archivos bajó (`downloaded`):

```json
{
  "object": "sat_declarations_refresh",
  "livemode": true,
  "issuer": "iss_OufpKqnrvx9p",
  "status": "completed",
  "found": 58,
  "downloaded": 112,
  "pending": 0,
  "warning": null,
  "refreshed_at": "2026-10-26T09:12:00-06:00",
  "next_refresh_at": "2026-10-26T09:22:00-06:00"
}
```

La consulta contesta en menos de un minuto. Un RFC con muchos años puede no alcanzar a bajar todo: entonces llega `status: "processing"` con lo que falta en `pending`, y lo demás se baja solo en la siguiente hora, sin otro timbre. Si una parte del SAT falló (por ejemplo, la anual) y lo demás sí llegó, `warning` trae lo que dijo el SAT.

## Listar las declaraciones

```bash tab="cURL"
curl -G https://api.fiscalisto.com/v1/sat_declarations \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -d issuer=iss_OufpKqnrvx9p \
  -d year=2026
```

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

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

for await (const item of fiscalisto.satDeclarations.list({ issuer: "iss_OufpKqnrvx9p", year: 2026 })) {
  console.log(item.id);
}
```

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

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

for item in fiscalisto.sat_declarations.list({"issuer": "iss_OufpKqnrvx9p", "year": 2026}):
    print(item["id"])
```

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

use Fiscalisto\Fiscalisto;

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

foreach ($fiscalisto->satDeclarations->list(['issuer' => 'iss_OufpKqnrvx9p', 'year' => 2026]) as $item) {
    echo $item['id'], "\n";
}
```

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

	for item, err := range client.SatDeclarations.ListAutoPaging(ctx, &fiscalisto.ListSatDeclarationsParams{
		Issuer: fiscalisto.String("iss_OufpKqnrvx9p"),
		Year:   fiscalisto.Int64(2026),
	}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(item.ID)
	}
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.model.ListSatDeclarationsParams;

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

for (var item : fiscalisto.satDeclarations().listAutoPaging(new ListSatDeclarationsParams()
        .setIssuer("iss_OufpKqnrvx9p")
        .setYear(2026))) {
    System.out.println(item.getId());
}
```

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

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

await foreach (var item in fiscalisto.SatDeclarations.ListAutoPagingAsync(new ListSatDeclarationsParams
{
    Issuer = "iss_OufpKqnrvx9p",
    Year = 2026,
}))
    Console.WriteLine(item.Id);
```

Salen del ejercicio y mes más recientes a los más antiguos, la anual antes de los meses de su año. Filtre por `year`, `month` (1 a 12), `type` (`normal` o `complementary`) y `source`: `monthly`, `annual` o `dyp`. Cada declaración trae:

- `period`, `type` (`normal` o `complementary`), `operation_number`, `filed_on` y `payment_line`.
- `isr_due`, `vat_due` y `total_due`, del acuse, y `profit_coefficient` en el ISR de personas morales.
- `sections`: cada impuesto con sus renglones como los imprime el SAT (`label` y `value`). En las de Declaraciones y pagos va vacío: su PDF trae dos columnas que no se leen con certeza, así que use el PDF.
- `summary`: las mismas cifras con nombres fijos, por obligación (ver abajo).
- `receipt`: los conceptos del acuse con lo que quedó a cargo y a pagar.
- `files`: qué archivos ya tiene, y en `files_error` por qué falta alguno, como lo dijo el SAT.

## Las cifras con nombres fijos

El SAT cambia el formato y los nombres de sus renglones de un año a otro, y repite algunos («CANTIDAD A CARGO» sale varias veces). `summary` los lee por usted: cada obligación de la declaración con sus cifras bajo nombres que no cambian, para comparar un mes con otro o con sus facturas sin conocer el formato del SAT.

```json
{
  "obligations": [
    {
      "obligation": "vat",
      "name": "Impuesto al Valor Agregado. Personas morales",
      "read": true,
      "amount_due": 186287,
      "amount_to_pay": 186287,
      "figures": {
        "taxable_16": 13622057,
        "charged": 2179529,
        "creditable": 1993242,
        "withheld": 0,
        "balance_applied": 0,
        "due": 186287,
        "in_favor": null,
        "to_pay": 186287
      }
    }
  ],
  "total_to_pay": 186287
}
```

| `obligation` | Qué es | Cifras además de las de todas |
| --- | --- | --- |
| `isr` | ISR propio (pago provisional) | `income`, `invoiced_income`, `income_ytd`, `deductions`, `profit_coefficient`, `taxable_profit`, `losses_applied`, `tax_base`, `tax_caused`, `prior_payments`, `withheld` |
| `vat` | IVA | `taxable_16`, `taxable_0`, `exempt`, `charged`, `paid_16`, `creditable`, `withheld`, `balance_applied` |
| `isr_salaries` | ISR retenido por salarios | `workers`, `payments`, `exempt`, `withheld` |
| `isr_assimilated_salaries` | ISR retenido por asimilados a salarios | `payments`, `withheld` |
| `isr_professional_services`, `isr_rent` | ISR retenido por servicios profesionales o arrendamiento | `withheld` |
| `vat_withholdings` | IVA retenido a terceros | `withheld` |
| `ieps`, `other` | IEPS y lo demás | `charged` en IEPS |

Todas traen `surcharges` (recargos), `inflation` (actualización), `paid_before` (lo pagado antes, en una complementaria), `due`, `in_favor` y `to_pay`. Una cifra que la declaración no trae o que no se pudo leer es `null`, nunca `0`. Si una obligación solo viene en el acuse (`read: false`), trae sus montos `amount_due` y `amount_to_pay` y sus cifras en `null`; así llegan siempre las de Declaraciones y pagos.

## El año mes por mes

`GET /v1/sat_declarations/calendar?year=2026` arma el ejercicio con lo que trajeron sus consultas: cada mes con sus obligaciones y si están presentadas (`filed`, con sus declaraciones), si faltan (`missing`: el plazo venció y no la encontramos) o si aún no vencen (`due`), con el día en que vencen en `due_on`. En persona moral trae también la anual (`month: null`). No usa timbres.

```bash tab="cURL"
curl -G https://api.fiscalisto.com/v1/sat_declarations/calendar \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -d issuer=iss_OufpKqnrvx9p \
  -d year=2026
```

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

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

const satDeclarationCalendar = await fiscalisto.satDeclarations.calendar({ issuer: "iss_OufpKqnrvx9p", year: 2026 });
```

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

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

sat_declaration_calendar = fiscalisto.sat_declarations.calendar({"issuer": "iss_OufpKqnrvx9p", "year": 2026})
```

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

use Fiscalisto\Fiscalisto;

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

$satDeclarationCalendar = $fiscalisto->satDeclarations->calendar(['issuer' => 'iss_OufpKqnrvx9p', 'year' => 2026]);
```

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

	satDeclarationCalendar, err := client.SatDeclarations.Calendar(ctx, &fiscalisto.GetSatDeclarationCalendarParams{
		Issuer: fiscalisto.String("iss_OufpKqnrvx9p"),
		Year:   fiscalisto.Int64(2026),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *satDeclarationCalendar)
}
```

```java tab="Java"
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.model.GetSatDeclarationCalendarParams;

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

var satDeclarationCalendar = fiscalisto.satDeclarations().calendar(new GetSatDeclarationCalendarParams()
        .setIssuer("iss_OufpKqnrvx9p")
        .setYear(2026));
System.out.println(satDeclarationCalendar);
```

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

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

var satDeclarationCalendar = await fiscalisto.SatDeclarations.CalendarAsync(new GetSatDeclarationCalendarParams
{
    Issuer = "iss_OufpKqnrvx9p",
    Year = 2026,
});
```

```json
{
  "object": "sat_declaration_calendar",
  "livemode": true,
  "issuer": "iss_OufpKqnrvx9p",
  "year": 2026,
  "missing": 1,
  "months": [
    {
      "month": 8,
      "due_on": "2026-09-18",
      "obligations": [
        { "obligation": "isr", "status": "filed", "declarations": ["dcl_OufpKqnrvx9p1E"] },
        { "obligation": "vat", "status": "filed", "declarations": ["dcl_OufpKqnrvx9p1E"] },
        { "obligation": "isr_salaries", "status": "missing", "declarations": [] }
      ]
    }
  ]
}
```

El SAT no dice qué obligaciones tiene un RFC, así que se deducen de lo que presenta: ISR e IVA cada mes desde el primero que presentó, y una retención si la presentó en 2 de los 3 meses anteriores, o antes y después del mes. Una retención que el emisor dejó de presentar (ya no tiene empleados) deja de pedirse a los dos meses. La opinión de cumplimiento del SAT es la que manda; use `missing` para avisarle a su cliente, no como dictamen.

## Webhooks

Cada consulta avisa a sus [webhooks](https://fiscalisto.com/docs/api/webhooks):

- `sat_declaration.created` cuando encuentra una declaración nueva. Sus archivos y cifras pueden llegar un momento después.
- `sat_declaration.updated` cuando llega su PDF, su acuse, los estados financieros o sus cifras.

En ambos, `data.object` es la declaración como queda.

## Descargar el PDF y el acuse

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/sat_declarations/dcl_OufpKqnrvx9p1F/pdf \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -o declaracion.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.satDeclarations.pdf("dcl_OufpKqnrvx9p1F"));
```

```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.sat_declarations.pdf("dcl_OufpKqnrvx9p1F"))
```

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

use Fiscalisto\Fiscalisto;

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

file_put_contents('factura.pdf', $fiscalisto->satDeclarations->pdf('dcl_OufpKqnrvx9p1F'));
```

```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.SatDeclarations.PDF(ctx, "dcl_OufpKqnrvx9p1F")
	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.satDeclarations().pdf("dcl_OufpKqnrvx9p1F"));
```

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

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

await File.WriteAllBytesAsync("factura.pdf", await fiscalisto.SatDeclarations.PdfAsync("dcl_OufpKqnrvx9p1F"));
```

El acuse está en `GET /v1/sat_declarations/{id}/receipt` y, en la anual de persona moral, el Excel de estados financieros en `GET /v1/sat_declarations/{id}/financial_statements`. Un archivo que el SAT aún no da contesta `404` con su motivo; se vuelve a pedir en la siguiente consulta.

> **Con permiso del dueño.** Pida la e.firma solo con el permiso del dueño del RFC y dígale para qué es. Con ella se consultan sus declaraciones y sus facturas en el SAT.
