# Validar los datos fiscales de un cliente

`POST https://api.fiscalisto.com/v1/tax_ids/validate`

Antes de timbrar: si el RFC, el nombre, el régimen, el código postal y el uso van a pasar. Sin cif_id revisa lo que se puede revisar sin el SAT (formato, régimen para ese tipo de persona, código postal en el catálogo, uso para el régimen, nombre sin «S.A. de C.V.») y las listas del SAT. Con el idCIF de la constancia lee el registro del SAT y compara nombre, código postal y régimen, como hará el PAC. No usa timbres.

## 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 |
| --- | --- | --- | --- |
| `tax_id` | string | sí | El RFC del cliente. (hasta 20 caracteres) |
| `legal_name` | string |  | El nombre o razón social que va a poner en la factura. (hasta 300 caracteres) |
| `tax_system` | string |  | Su régimen fiscal (c_RegimenFiscal), como 601 o 612. |
| `zip` | string |  | El código postal de su domicilio fiscal. |
| `use` | string |  | El uso del CFDI (c_UsoCFDI), como G03. |
| `cif_id` | string |  | El idCIF de su constancia de situación fiscal (11 dígitos, arriba a la izquierda, junto al QR). Con él se compara todo con lo que tiene el SAT. |

Ejemplo:

```json
{
  "tax_id": "ICV060329BY0",
  "legal_name": "Inmobiliaria CVA, S.A. de C.V.",
  "tax_system": "601",
  "zip": "33800",
  "use": "G03",
  "cif_id": "12345678901"
}
```

## Con el SDK de TypeScript

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

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

const taxIdValidation = await fiscalisto.taxIds.validate({
  tax_id: "ICV060329BY0",
  legal_name: "Inmobiliaria CVA, S.A. de C.V.",
  tax_system: "601",
  zip: "33800",
  use: "G03",
  cif_id: "12345678901",
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

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

tax_id_validation = fiscalisto.tax_ids.validate({
    "tax_id": "ICV060329BY0",
    "legal_name": "Inmobiliaria CVA, S.A. de C.V.",
    "tax_system": "601",
    "zip": "33800",
    "use": "G03",
    "cif_id": "12345678901",
}, 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();

$taxIdValidation = $fiscalisto->taxIds->validate([
    'tax_id' => 'ICV060329BY0',
    'legal_name' => 'Inmobiliaria CVA, S.A. de C.V.',
    'tax_system' => '601',
    'zip' => '33800',
    'use' => 'G03',
    'cif_id' => '12345678901',
], ['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 taxIdValidation = await fiscalisto.TaxIds.ValidateAsync(new ValidateTaxIdParams
{
    TaxId = "ICV060329BY0",
    LegalName = "Inmobiliaria CVA, S.A. de C.V.",
    TaxSystem = "601",
    Zip = "33800",
    Use = "G03",
    CifId = "12345678901",
}, 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()

	taxIDValidation, err := client.TaxIds.Validate(ctx, &fiscalisto.ValidateTaxIdParams{
		TaxID:     "ICV060329BY0",
		LegalName: fiscalisto.String("Inmobiliaria CVA, S.A. de C.V."),
		TaxSystem: fiscalisto.String("601"),
		Zip:       fiscalisto.String("33800"),
		Use:       fiscalisto.String("G03"),
		CifID:     fiscalisto.String("12345678901"),
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *taxIDValidation)
}
```

## Con el SDK de Java

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

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

var taxIdValidation = fiscalisto.taxIds().validate(new ValidateTaxIdParams()
        .setTaxId("ICV060329BY0")
        .setLegalName("Inmobiliaria CVA, S.A. de C.V.")
        .setTaxSystem("601")
        .setZip("33800")
        .setUse("G03")
        .setCifId("12345678901"), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(taxIdValidation);
```

## Respuesta 200

Correcto.

Un objeto `TaxIdValidation`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `object` | `"tax_id_validation"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `tax_id` | string | sí | El RFC revisado. |
| `kind` | `company`, `person`, `generic` | sí | company (persona moral, 12 caracteres), person (persona física, 13) o generic (XAXX010101000, XEXX010101000). |
| `valid` | boolean | sí | true si no hay errores: con lo que mandó, el SAT no debería rechazar la factura por los datos del cliente. |
| `checked_with_sat` | boolean | sí | true si se comparó con el registro del SAT (mandó cif_id y el SAT contestó). |
| `errors` | arreglo de objeto | sí | Lo que haría que el SAT rechace la factura. Cada uno con el campo (param), un código, la explicación y, si se puede, el valor correcto (suggestion). |
| `errors[].param` | string | sí | El campo: tax_id, legal_name, tax_system, zip, use o cif_id. |
| `errors[].code` | string | sí | Qué falló, para su código: tax_id_format, tax_id_date, legal_name_capital_regime, legal_name_mismatch, tax_system_person, tax_system_mismatch, zip_unknown, zip_mismatch, use_tax_system, cif_id_not_found… |
| `errors[].message` | string | sí | La explicación, para mostrarla a su usuario. |
| `errors[].suggestion` | string o null | sí | El valor correcto cuando se sabe (el del SAT con cif_id, o el nombre sin régimen de capital); null si no. |
| `warnings` | arreglo de objeto | sí | Lo que no impide timbrar pero conviene revisar: el dígito verificador, mayúsculas, si el RFC está en las listas del SAT. |
| `warnings[].param` | string | sí | El campo. |
| `warnings[].code` | string | sí | tax_id_check_digit, legal_name_format, tax_id_listed_69b o tax_id_listed_69. |
| `warnings[].message` | string | sí | La explicación. |
| `warnings[].suggestion` | string o null | sí | El valor sugerido, o null. |
| `sat_record` | objeto o null | sí | Lo que tiene el SAT en la constancia (con cif_id): nombre, código postal y regímenes vigentes. null sin cif_id. |
| `sat_record.legal_name` | string o null | sí | El nombre o razón social, como lo tiene el SAT. |
| `sat_record.zip` | string o null | sí | El código postal de su domicilio fiscal. |
| `sat_record.tax_systems` | arreglo de string | sí | Sus regímenes vigentes (c_RegimenFiscal). |
| `sat_error` | string o null | sí | Si el SAT no contestó a tiempo (con cif_id): reintente en unos minutos. null si contestó o no se consultó. |
| `sat_lists` | objeto o null | sí | Si el RFC aparece en las listas del SAT. null con un RFC genérico o mal escrito. |
| `sat_lists.object` | `"sat_list_check"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `sat_lists.tax_id` | string | sí | El RFC revisado. |
| `sat_lists.name` | string o null | sí | El nombre con que aparece en las listas del SAT (null si no aparece). |
| `sat_lists.listed` | boolean | sí | true si el RFC aparece en alguna lista, aunque haya desvirtuado. |
| `sat_lists.risk` | `high`, `medium`, `none`, `unknown` | sí | high: 69-B o 69-B Bis como presunto o definitivo (el SAT dice que simula operaciones; sus facturas no se pueden deducir). medium: una lista del art. 69 (no localizado, créditos firmes o exigibles, cancelados, sentencias, CSD sin efectos). none: no aparece en ninguna, con todas las listas al día, o ya desvirtuó o tiene sentencia favorable. unknown: no aparece, pero alguna lista no se pudo actualizar (vea lists_unavailable): no lo dé por limpio. |
| `sat_lists.verified` | boolean | sí | true si todas las listas se leyeron con éxito en los últimos dos días. Con false, que no aparezca no significa que esté limpio. |
| `sat_lists.lists` | arreglo de objeto | sí | Cada lista en que aparece; vacía si no aparece en ninguna. |
| `sat_lists.lists[].list` | `69`, `69b`, `69b_bis` | sí | 69b: art. 69-B (operaciones simuladas). 69b_bis: art. 69-B Bis (pérdidas fiscales). 69: art. 69 (no localizados, adeudos, cancelados). |
| `sat_lists.lists[].source` | string | sí | El archivo del SAT de donde viene (clave). |
| `sat_lists.lists[].source_name` | string | sí | El nombre del archivo del SAT, para mostrarlo. |
| `sat_lists.lists[].situation` | string o null | sí | Su situación según el SAT: Presunto, Definitivo, Desvirtuado, Sentencia favorable; en el art. 69, el supuesto (null si el archivo no la trae). |
| `sat_lists.lists[].published_on` | string o null | sí | Fecha de publicación en el SAT o en el DOF (null si no la trae). |
| `sat_lists.lists[].details` | objeto o null | sí | Lo demás que publica el SAT para ese RFC (oficios, fechas, montos), tal cual; null si nada. |
| `sat_lists.lists_updated_at` | string (date-time) o null | sí | Cuándo se actualizaron las listas por última vez (cada día a las 00:00 de la Ciudad de México). |
| `sat_lists.lists_unavailable` | arreglo de string | sí | Las listas que no se pudieron confirmar (su última actualización falló, falta o tiene más de dos días). Vacía si todas están al día. |

```json
{
  "object": "tax_id_validation",
  "tax_id": "ICV060329BY0",
  "kind": "company",
  "valid": false,
  "checked_with_sat": true,
  "errors": [
    {
      "param": "legal_name",
      "code": "legal_name_capital_regime",
      "message": "Sin «S.A. de C.V.»: en CFDI 4.0 el nombre va sin régimen de capital, como en la constancia.",
      "suggestion": "INMOBILIARIA CVA"
    },
    {
      "param": "zip",
      "code": "zip_mismatch",
      "message": "El código postal no es el del domicilio fiscal que tiene el SAT.",
      "suggestion": "33826"
    }
  ],
  "warnings": [],
  "sat_record": {
    "legal_name": "INMOBILIARIA CVA",
    "zip": "33826",
    "tax_systems": [
      "601"
    ]
  },
  "sat_error": null,
  "sat_lists": {
    "object": "sat_list_check",
    "tax_id": "ICV060329BY0",
    "name": null,
    "listed": false,
    "risk": "none",
    "verified": true,
    "lists": [],
    "lists_updated_at": "2026-10-24T00:12:40-06:00",
    "lists_unavailable": []
  }
}
```

## 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.
