# Datos fiscales del cliente

> Revise el RFC, nombre, régimen, código postal y uso del CFDI de un cliente antes de timbrar, o mándele una liga para que él mismo los dé con su constancia.

Casi todos los rechazos del SAT vienen de los datos del cliente: un nombre con «S.A. de C.V.», un código postal que no es el de su constancia, un régimen que no le toca. Hay dos maneras de tenerlos bien antes de timbrar.

## Revisar los datos que ya tiene

`POST /v1/tax_ids/validate` revisa los datos sin timbrar ni gastar timbres, y le dice qué está mal y con qué valor corregirlo:

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/tax_ids/validate \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tax_id": "EKU9003173C9", "legal_name": "Escuela Kemper Urgate, S.A. de C.V.", "tax_system": "601", "zip": "42501", "use": "G03" }'
```

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

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

const taxIdValidation = await fiscalisto.taxIds.validate({
  tax_id: "EKU9003173C9",
  legal_name: "Escuela Kemper Urgate, S.A. de C.V.",
  tax_system: "601",
  zip: "42501",
  use: "G03",
});
```

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

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

tax_id_validation = fiscalisto.tax_ids.validate({
    "tax_id": "EKU9003173C9",
    "legal_name": "Escuela Kemper Urgate, S.A. de C.V.",
    "tax_system": "601",
    "zip": "42501",
    "use": "G03",
})
```

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

use Fiscalisto\Fiscalisto;

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

$taxIdValidation = $fiscalisto->taxIds->validate([
    'tax_id' => 'EKU9003173C9',
    'legal_name' => 'Escuela Kemper Urgate, S.A. de C.V.',
    'tax_system' => '601',
    'zip' => '42501',
    'use' => 'G03',
]);
```

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

	taxIDValidation, err := client.TaxIds.Validate(ctx, &fiscalisto.ValidateTaxIdParams{
		TaxID:     "EKU9003173C9",
		LegalName: fiscalisto.String("Escuela Kemper Urgate, S.A. de C.V."),
		TaxSystem: fiscalisto.String("601"),
		Zip:       fiscalisto.String("42501"),
		Use:       fiscalisto.String("G03"),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *taxIDValidation)
}
```

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

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

var taxIdValidation = fiscalisto.taxIds().validate(new ValidateTaxIdParams()
        .setTaxId("EKU9003173C9")
        .setLegalName("Escuela Kemper Urgate, S.A. de C.V.")
        .setTaxSystem("601")
        .setZip("42501")
        .setUse("G03"));
System.out.println(taxIdValidation);
```

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

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

var taxIdValidation = await fiscalisto.TaxIds.ValidateAsync(new ValidateTaxIdParams
{
    TaxId = "EKU9003173C9",
    LegalName = "Escuela Kemper Urgate, S.A. de C.V.",
    TaxSystem = "601",
    Zip = "42501",
    Use = "G03",
});
```

```json
{
  "object": "tax_id_validation",
  "tax_id": "EKU9003173C9",
  "kind": "company",
  "valid": false,
  "checked_with_sat": false,
  "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": "ESCUELA KEMPER URGATE"
    }
  ],
  "warnings": [],
  "sat_record": null,
  "sat_error": null,
  "sat_lists": { "object": "sat_list_check", "listed": false, "risk": "none" }
}
```

Sin más, revisa lo que se puede saber sin preguntarle al SAT: el formato y la fecha del RFC, el nombre, que el régimen sea de persona moral o física según el RFC, que el código postal exista, que el uso del CFDI vaya con el régimen, los RFC genéricos y si el RFC está en las [listas del SAT](https://fiscalisto.com/docs/api/listas-del-sat) (eso llega en `warnings`). Cada problema trae `param`, un `code` estable para su código, un `message` para mostrarle a su usuario y, cuando se puede, `suggestion` con el valor correcto.

### Compararlos con la constancia

Si además manda `cif_id`, el idCIF que viene en la constancia de situación fiscal (arriba a la derecha, junto al código QR), Fiscalisto consulta el registro del SAT y compara nombre, código postal y régimen con lo que usted mandó. Entonces `checked_with_sat` es `true` y `sat_record` trae lo que dice el SAT:

```json
"sat_record": { "legal_name": "ESCUELA KEMPER URGATE", "zip": "42501", "tax_systems": ["601"] }
```

Cada consulta al SAT cuenta en el [límite del día](https://fiscalisto.com/docs/api/limites); la misma constancia consultada dos veces en 24 horas cuenta una. Si el SAT tarda o no contesta, la revisión llega sin él, con el motivo en `sat_error`, y puede repetirla después.

## Pedirle sus datos al cliente

Si no tiene los datos, o no confía en los que le dieron, pídaselos con una liga. Su cliente la abre en Fiscalisto, sube su constancia (o escribe sus datos) y antes de aceptarlos se revisan igual que arriba. A usted le llega un webhook.

```bash tab="cURL"
curl https://api.fiscalisto.com/v1/customer_data_requests \
  -H "Authorization: Bearer $FISCALISTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reference": "Pedido 1042", "description": "Para facturar su pedido 1042", "expires_in_days": 7 }'
```

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

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

const customerDataRequest = await fiscalisto.customerDataRequests.create({
  reference: "Pedido 1042",
  description: "Para facturar su pedido 1042",
  expires_in_days: 7,
});
```

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

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

customer_data_request = fiscalisto.customer_data_requests.create({
    "reference": "Pedido 1042",
    "description": "Para facturar su pedido 1042",
    "expires_in_days": 7,
})
```

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

use Fiscalisto\Fiscalisto;

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

$customerDataRequest = $fiscalisto->customerDataRequests->create([
    'reference' => 'Pedido 1042',
    'description' => 'Para facturar su pedido 1042',
    'expires_in_days' => 7,
]);
```

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

	customerDataRequest, err := client.CustomerDataRequests.Create(ctx, &fiscalisto.CreateCustomerDataRequestParams{
		Reference:     fiscalisto.String("Pedido 1042"),
		Description:   fiscalisto.String("Para facturar su pedido 1042"),
		ExpiresInDays: fiscalisto.Int64(7),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(customerDataRequest.ID)
}
```

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

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

var customerDataRequest = fiscalisto.customerDataRequests().create(new CreateCustomerDataRequestParams()
        .setReference("Pedido 1042")
        .setDescription("Para facturar su pedido 1042")
        .setExpiresInDays(7));
System.out.println(customerDataRequest.getId());
```

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

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

var customerDataRequest = await fiscalisto.CustomerDataRequests.CreateAsync(new CreateCustomerDataRequestParams
{
    Reference = "Pedido 1042",
    Description = "Para facturar su pedido 1042",
    ExpiresInDays = 7,
});
```

```json
{
  "id": "cdr_…",
  "object": "customer_data_request",
  "status": "open",
  "url": "https://fiscalisto.com/datos/…",
  "reference": "Pedido 1042",
  "expires_at": "2026-10-31T12:00:00-06:00",
  "submission": null
}
```

Mándele `url` a su cliente como quiera: en su correo, en su página de pedido o por WhatsApp. También puede mostrarla dentro de su página, con `fiscalisto.js` o `@fiscalisto/react`, como la [autofactura](https://fiscalisto.com/docs/api/autofactura#en-su-página-con-fiscalistojs). `reference` es su id del cliente o del pedido y `description` una línea de para qué son los datos; el cliente ve las dos arriba del formulario, y `reference` le regresa en el evento. La liga sirve 60 días si no dice otra cosa.

Cuando el cliente manda sus datos llega el evento `customer_data_request.completed` con la solicitud completa. En `submission` vienen los datos y `customer`, el cliente (`cus_…`) del emisor que ya puede usar al facturar:

```json
"submission": {
  "tax_id": "PEPJ800101AB1",
  "legal_name": "JUAN PÉREZ LÓPEZ",
  "tax_system": "612",
  "zip": "06600",
  "use": "G03",
  "email": "juan@correo.mx",
  "source": "constancia",
  "customer": "cus_…",
  "applied": true
}
```

Un cliente nuevo se guarda directo en el catálogo del emisor (`applied: true`). Si el RFC ya era un cliente suyo y los datos cambian, no se sobrescribe solo: `applied` es `false` y usted decide si actualizarlo con `POST /v1/customers/{id}`. Así una liga no puede cambiar a quién se le mandan las facturas.

| Ruta | Qué hace |
| --- | --- |
| `POST /v1/customer_data_requests` | Crea una liga |
| `GET /v1/customer_data_requests` | Las ligas del emisor, de la más nueva a la más vieja |
| `GET /v1/customer_data_requests/{id}` | Una liga, con lo que mandó el cliente |
| `DELETE /v1/customer_data_requests/{id}` | La liga deja de servir (una completada no se cancela) |

`status` es `open`, `completed`, `expired` o `canceled`; `url` solo viene mientras la liga está abierta.
