# Calcular un recibo sin timbrar

`POST https://api.fiscalisto.com/v1/payroll_receipts/preview`

El recibo como se timbraría (percepciones, ISR con el subsidio para el empleo, cuotas IMSS y el neto), sin timbrar ni usar 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 |
| --- | --- | --- | --- |
| `employee` | string | sí | El empleado (emp_…). |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.start` | string | sí | Primer día del periodo (FechaInicialPago), AAAA-MM-DD. |
| `period.end` | string | sí | Último día del periodo (FechaFinalPago), AAAA-MM-DD. |
| `period.payment_date` | string |  | Fecha de pago (FechaPago), AAAA-MM-DD. Por omisión el último día del periodo. |
| `days` | number |  | Días pagados (NumDiasPagados). Por omisión, todos los del periodo que le tocan. (de -∞ a 31) |
| `send_email` | boolean |  | true para mandar el PDF y el XML por correo al timbrar, con el diseño de Fiscalisto. Por omisión no se envía. |
| `metadata` | objeto |  | Sus propios datos: hasta 50 llaves de 40 caracteres con valores de texto de hasta 500. No van al CFDI; vuelven en el objeto y en los webhooks. |

Ejemplo:

```json
{
  "employee": "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
  "period": {
    "start": "2026-10-10",
    "end": "2026-10-16"
  }
}
```

## Con el SDK de TypeScript

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

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

const payrollReceiptPreview = await fiscalisto.payrollReceipts.preview({
  employee: "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
  period: { start: "2026-10-10", end: "2026-10-16" },
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

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

payroll_receipt_preview = fiscalisto.payroll_receipts.preview({
    "employee": "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
    "period": {"start": "2026-10-10", "end": "2026-10-16"},
}, 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();

$payrollReceiptPreview = $fiscalisto->payrollReceipts->preview([
    'employee' => 'emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV',
    'period' => [
        'start' => '2026-10-10',
        'end' => '2026-10-16',
    ],
], ['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 payrollReceiptPreview = await fiscalisto.PayrollReceipts.PreviewAsync(new PreviewPayrollReceiptParams
{
    Employee = "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
    Period = new() { Start = "2026-10-10", End = "2026-10-16" },
}, 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()

	payrollReceiptPreview, err := client.PayrollReceipts.Preview(ctx, &fiscalisto.PreviewPayrollReceiptParams{
		Employee: "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
		Period: fiscalisto.PreviewPayrollReceiptParamsPeriod{
			Start: "2026-10-10",
			End:   "2026-10-16",
		},
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", *payrollReceiptPreview)
}
```

## Con el SDK de Java

```java
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.PreviewPayrollReceiptParams;
import com.fiscalisto.model.PreviewPayrollReceiptParamsPeriod;

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

var payrollReceiptPreview = fiscalisto.payrollReceipts().preview(new PreviewPayrollReceiptParams()
        .setEmployee("emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV")
        .setPeriod(new PreviewPayrollReceiptParamsPeriod()
                .setStart("2026-10-10")
                .setEnd("2026-10-16")), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(payrollReceiptPreview);
```

## Respuesta 200

Correcto.

Un objeto `PayrollReceiptPreview`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `object` | `"payroll_receipt_preview"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `employee` | string | sí | El empleado (emp_…). |
| `periodicity` | string | sí | Periodicidad del pago (PeriodicidadPago): 02 semanal, 03 catorcenal, 04 quincenal (por omisión), 05 mensual. |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.start` | string | sí | Primer día del periodo (FechaInicialPago), AAAA-MM-DD. |
| `period.end` | string | sí | Último día del periodo (FechaFinalPago), AAAA-MM-DD. |
| `period.payment_date` | string | sí | Fecha de pago (FechaPago), AAAA-MM-DD. Por omisión el último día del periodo. |
| `days` | number | sí | Días pagados (NumDiasPagados). Por omisión, todos los del periodo que le tocan. |
| `contribution_base_salary` | number | sí | Salario base de cotización (SalarioBaseCotApor). |
| `perceptions` | arreglo de objeto | sí | Percepciones (Percepcion): sueldo y demás, gravado y exento. |
| `perceptions[].type` | string | sí | Tipo de percepción (TipoPercepcion), c_TipoPercepcion: 001 sueldos… |
| `perceptions[].key` | string | sí | Clave del patrón (Clave). |
| `perceptions[].concept` | string | sí | Concepto (Concepto). |
| `perceptions[].taxed` | number | sí | Importe gravado (ImporteGravado). |
| `perceptions[].exempt` | number | sí | Importe exento (ImporteExento). |
| `deductions` | arreglo de objeto | sí | Deducciones (Deduccion): ISR, cuotas IMSS y demás. |
| `deductions[].type` | string | sí | Tipo de deducción (TipoDeduccion), c_TipoDeduccion: 001 IMSS, 002 ISR… |
| `deductions[].key` | string | sí | Clave del patrón (Clave). |
| `deductions[].concept` | string | sí | Concepto (Concepto). |
| `deductions[].amount` | number | sí | Importe (Importe). |
| `other_payments` | arreglo de objeto | sí | Otros pagos (OtroPago): subsidio para el empleo. |
| `other_payments[].type` | string | sí | Tipo de otro pago (TipoOtroPago), c_TipoOtroPago: 002 subsidio para el empleo. |
| `other_payments[].key` | string | sí | Clave del patrón (Clave). |
| `other_payments[].concept` | string | sí | Concepto (Concepto). |
| `other_payments[].amount` | number | sí | Importe pagado (Importe). |
| `other_payments[].subsidy_caused` | number |  | Subsidio causado (SubsidioCausado). |
| `other_payments[].subsidy_applied` | number |  | Del subsidio causado, el ISR que evitó (no va en el XML). |
| `isr` | objeto | sí | El cálculo del ISR del periodo: base, tarifa, subsidio y resultado. |
| `isr.tariff` | number | sí | ISR según la tarifa del periodo. |
| `isr.subsidy` | number | sí | Subsidio para el empleo causado. |
| `isr.withheld` | number | sí | ISR retenido (tarifa menos subsidio, no menos de 0). |
| `isr.exempt_minimum` | boolean | sí | true si gana el salario mínimo: no se le retiene ISR. |
| `isr.adjustment` | objeto |  | El ajuste de fin de mes: subsidio revertido y el ISR que retiene. |
| `isr.adjustment.reversed` | number | sí | Subsidio causado antes en el mes que se revierte. |
| `isr.adjustment.isr` | number | sí | El cálculo del ISR del periodo: base, tarifa, subsidio y resultado. |
| `totals` | objeto | sí | Totales: percepciones, deducciones, otros pagos y el neto a pagar. |
| `totals.salaries` | number | sí | Total de sueldos, salarios y asimilados (TotalSueldos). |
| `totals.taxed` | number | sí | Total gravado (TotalGravado). |
| `totals.exempt` | number | sí | Total exento (TotalExento). |
| `totals.perceptions` | number | sí | Total de percepciones (TotalPercepciones). |
| `totals.other_deductions` | number | sí | Otras deducciones (TotalOtrasDeducciones). |
| `totals.taxes_withheld` | number | sí | Impuestos retenidos (TotalImpuestosRetenidos). |
| `totals.deductions` | number | sí | Total de deducciones (TotalDeducciones). |
| `totals.other_payments` | number | sí | Total de otros pagos (TotalOtrosPagos). |
| `totals.subtotal` | number | sí | Subtotal del comprobante: percepciones más otros pagos. |
| `totals.net` | number | sí | Neto a pagar al empleado. |

```json
{
  "object": "payroll_receipt_preview",
  "employee": "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
  "periodicity": "02",
  "period": {
    "start": "2026-10-10",
    "end": "2026-10-16",
    "payment_date": "2026-10-16"
  },
  "days": 7,
  "contribution_base_salary": 334.66,
  "perceptions": [
    {
      "type": "001",
      "key": "001",
      "concept": "Sueldo",
      "taxed": 2240,
      "exempt": 0
    }
  ],
  "deductions": [
    {
      "type": "001",
      "key": "001",
      "concept": "Cuotas IMSS",
      "amount": 55.63
    },
    {
      "type": "002",
      "key": "002",
      "concept": "ISR",
      "amount": 37.73
    }
  ],
  "other_payments": [
    {
      "type": "002",
      "key": "002",
      "concept": "Subsidio para el empleo del Decreto que otorga el subsidio para el empleo (DOF 1 de mayo de 2024)",
      "amount": 0,
      "subsidy_caused": 123.34,
      "subsidy_applied": 123.34
    }
  ],
  "isr": {
    "tariff": 161.07,
    "subsidy": 123.34,
    "withheld": 37.73,
    "exempt_minimum": false
  },
  "totals": {
    "salaries": 2240,
    "taxed": 2240,
    "exempt": 0,
    "perceptions": 2240,
    "other_deductions": 55.63,
    "taxes_withheld": 37.73,
    "deductions": 93.36,
    "other_payments": 0,
    "subtotal": 2240,
    "net": 2146.64
  }
}
```

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