# Timbrar una constancia de retenciones

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

Timbra una constancia de retenciones e información de pagos (Retenciones 2.0) con los folios RET1, RET2… del emisor. Una vez por Idempotency-Key; con send_email y email la manda al receptor al timbrarla.

## Parámetros

| Nombre | Dónde | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `Idempotency-Key` | encabezado | sí | Uno nuevo por comprobante (8 a 255 caracteres; su id de pedido sirve). Si la respuesta se pierde, repita la solicitud con el mismo valor: contesta lo mismo y nunca se timbra dos veces. |

## Cuerpo

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `issuer` | string |  | Emisor (iss_…). Si la llave tiene un solo emisor o la cuenta tiene uno solo, puede omitirse. |
| `code` | string | sí | Clave de la retención (CveRetenc), c_CveRetenc: 01 servicios profesionales, 05 arrendamiento, 14 dividendos, 16 intereses, 18 pagos al extranjero… Las claves 14, 16, 17 y 18 a 24 llevan su complemento (dividends, interest, trust_lease, foreign_payment, share_sale, prize, trust, retirement_plan, mortgage_interest, financial_derivatives); la 26 (plataformas tecnológicas) aún no se puede emitir. |
| `description` | string o null |  | Descripción de la retención (DescRetenc); obligatoria con la clave 25 (otro tipo). |
| `recipient` | objeto | sí | Receptor de la constancia (Receptor): nacional con RFC y código postal, o extranjero. |
| `recipient.foreign` | boolean |  | true si el receptor es extranjero (sin RFC). |
| `recipient.tax_id` | string o null |  | RFC (Rfc), 12 caracteres una persona moral y 13 una física. |
| `recipient.legal_name` | string | sí | Nombre o razón social tal como está en la constancia de situación fiscal, sin el régimen de capital (sin «S.A. de C.V.»). (hasta 300 caracteres) |
| `recipient.zip` | string |  | Código postal del domicilio fiscal, 5 dígitos, como en la constancia de situación fiscal. El de un emisor es el lugar de expedición (LugarExpedicion) de sus comprobantes. |
| `recipient.curp` | string o null |  | CURP, 18 caracteres. |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.year` | integer | sí | Año (Ejercicio). (de 2004 a 2100) |
| `period.month` | integer |  | Un solo mes, del 1 al 12 (MesIni y MesFin iguales). (de 1 a 12) |
| `period.from_month` | integer |  | Mes inicial (MesIni), 1 a 12. (de 1 a 12) |
| `period.to_month` | integer |  | Mes final (MesFin), 1 a 12, del mismo año. (de 1 a 12) |
| `totals` | objeto | sí | Totales (Totales). |
| `totals.operation` | number | sí | Monto total de la operación (MontoTotOperacion). (de 0 a ∞) |
| `totals.taxed` | number |  | Monto gravado (MontoTotGrav). Por omisión, operation menos exempt. (de 0 a ∞) |
| `totals.exempt` | number |  | Monto exento (MontoTotExent). Por omisión 0. (de 0 a ∞) |
| `taxes` | arreglo de objeto | sí | Impuestos del comprobante, por tipo. (hasta 50) |
| `taxes[].tax` | string | sí | Impuesto: isr, iva o ieps (ImpuestoRet 001, 002, 003). |
| `taxes[].base` | number | sí | Base del impuesto retenido (BaseRet). (de 0 a ∞) |
| `taxes[].amount` | number | sí | Monto retenido (MontoRet). (de 0 a ∞) |
| `taxes[].payment_type` | string |  | Tipo de pago de la retención (TipoPagoRet): 01 definitivo IVA, 02 definitivo IEPS, 03 definitivo ISR, 04 provisional ISR. Por omisión el usual de cada impuesto. |
| `dividends` | objeto |  | Complemento de dividendos. |
| `dividends.type` | `01`, `02`, `03`, `04`, `05`, `06` | sí | Tipo de dividendo o utilidad distribuida (CveTipDivOUtil), c_TipoDividendoOUtilidadDistribuida. |
| `dividends.isr_mexico` | number | sí | ISR acreditable en México (MontISRAcredRetMexico). (de 0 a ∞) |
| `dividends.isr_foreign` | number | sí | ISR acreditable en el extranjero (MontISRAcredRetExtranjero). (de 0 a ∞) |
| `dividends.foreign_retention` | number o null |  | Retención en el extranjero sobre dividendos (MontRetExtDivExt). |
| `dividends.company` | `nacional`, `extranjera` | sí | Tipo de sociedad que distribuye (TipoSocDistrDiv): nacional o extranjera. |
| `dividends.national_credit` | number o null |  | ISR acreditable nacional (MontISRAcredNal). |
| `dividends.accumulated_national` | number o null |  | Dividendo acumulable nacional (MontDivAcumNal). |
| `dividends.accumulated_foreign` | number o null |  | Dividendo acumulable extranjero (MontDivAcumExt). |
| `interest` | objeto |  | Complemento de intereses. |
| `interest.financial_system` | boolean | sí | true si los intereses vienen del sistema financiero (SistFinanciero). |
| `interest.retirement` | boolean | sí | true si se retiraron los intereses en el periodo (RetiroAORESRetInt). |
| `interest.derivatives` | boolean | sí | true si son operaciones financieras derivadas (OperFinancDerivad). |
| `interest.nominal` | number | sí | Interés nominal (MontIntNominal). |
| `interest.real` | number | sí | Interés real (MontIntReal). |
| `interest.loss` | number | sí | Pérdida (Perdida). |
| `foreign_payment` | objeto |  | Complemento de pagos a extranjeros. |
| `foreign_payment.beneficiary` | boolean | sí | true si quien recibe es el beneficiario efectivo (EsBenefEfectDelCobro). |
| `foreign_payment.country` | string o null |  | País de residencia del extranjero (PaisDeResidParaEfecFisc), 2 letras. |
| `foreign_payment.concept` | `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9` | sí | Concepto del pago (ConceptoPago), c_TipoContribuyenteSujetoRetencion. |
| `foreign_payment.description` | string | sí | Descripción del concepto (DescripcionConcepto). (hasta 255 caracteres) |
| `foreign_payment.beneficiary_tax_id` | string o null |  | RFC del beneficiario, si no es quien recibe (RFC). |
| `foreign_payment.beneficiary_curp` | string o null |  | CURP del beneficiario (CURP). |
| `foreign_payment.beneficiary_name` | string o null |  | Nombre o razón social del beneficiario (NomDenRazSocB). |
| `trust_lease` | objeto |  | Complemento de arrendamiento en fideicomiso (Arrendamientoenfideicomiso 1.0), obligatorio con code 17. |
| `trust_lease.trustee_payment` | number | sí | Pago provisional que el fiduciario efectuó al arrendador en el periodo (PagProvEfecPorFiduc). (de 0 a ∞) |
| `trust_lease.income` | number | sí | Rendimientos del periodo por el arrendamiento de los bienes (RendimFideicom). (de 0 a ∞) |
| `trust_lease.deductions` | number | sí | Deducciones del arrendamiento en el periodo (DeduccCorresp). (de 0 a ∞) |
| `trust_lease.withheld_total` | number o null |  | Monto total retenido del arrendamiento en el periodo (MontTotRet). |
| `trust_lease.fibra_result` | number o null |  | Resultado fiscal distribuido por FIBRAS (MontResFiscDistFibras). |
| `trust_lease.other_amount` | number o null |  | Monto de otros conceptos distribuidos (MontOtrosConceptDistr). |
| `trust_lease.other_description` | string o null |  | Qué son los otros conceptos distribuidos (DescrMontOtrosConceptDistr); obligatoria con other_amount. |
| `share_sale` | objeto |  | Complemento de enajenación de acciones u operaciones de valores (EnajenaciondeAcciones 1.0), obligatorio con code 19. |
| `share_sale.contract` | string | sí | Descripción del contrato de intermediación (ContratoIntermediacion). (hasta 300 caracteres) |
| `share_sale.gain` | number | sí | Ganancia obtenida (Ganancia). (de 0 a ∞) |
| `share_sale.loss` | number | sí | Pérdida (Perdida). (de 0 a ∞) |
| `prize` | objeto |  | Complemento de premios (Premios 1.0), obligatorio con code 20. Sus montos son los de totals. |
| `prize.state` | string | sí | Entidad federativa donde se paga el premio (EntidadFederativa), c_EntidadesFederativas de catRetenciones: 01 Aguascalientes … 09 Ciudad de México … 32 Zacatecas. |
| `trust` | objeto |  | Complemento de fideicomisos que no realizan actividades empresariales (Fideicomisonoempresarial 1.0), obligatorio con code 21. |
| `trust.income` | objeto | sí | Ingresos o entradas del fideicomiso en el periodo (IngresosOEntradas) y la parte del receptor. |
| `trust.income.concept` | string | sí | Concepto de los ingresos (IntegracIngresos/Concepto), hasta 100 caracteres. (hasta 100 caracteres) |
| `trust.income.total` | number | sí | Ingresos totales del fideicomiso en el periodo (MontTotEntradasPeriodo). (de 0 a ∞) |
| `trust.income.share` | number | sí | Parte proporcional de los ingresos acumulables del receptor (PartPropAcumDelFideicom). (de 0 a ∞) |
| `trust.income.proportion` | number | sí | Proporción de participación del receptor según el contrato (PropDelMontTot). (de 0 a 999.999999) |
| `trust.deductions` | objeto | sí | Deducciones o salidas del fideicomiso en el periodo (DeduccOSalidas) y la parte del receptor. |
| `trust.deductions.concept` | string | sí | Concepto de los egresos (IntegracEgresos/ConceptoS), hasta 100 caracteres. (hasta 100 caracteres) |
| `trust.deductions.total` | number | sí | Egresos totales del fideicomiso en el periodo (MontTotEgresPeriodo). (de 0 a ∞) |
| `trust.deductions.share` | number | sí | Parte proporcional de las deducciones autorizadas del receptor (PartPropDelFideicom). (de 0 a ∞) |
| `trust.deductions.proportion` | number | sí | Proporción de participación del receptor según el contrato (PropDelMontTot). (de 0 a 999.999999) |
| `trust.withholding` | objeto | sí | Retención efectuada al fideicomiso (RetEfectFideicomiso). |
| `trust.withholding.amount` | number | sí | Monto de la retención (MontRetRelPagFideic). (de 0 a ∞) |
| `trust.withholding.description` | string | sí | Descripción de la retención (DescRetRelPagFideic), hasta 100 caracteres. (hasta 100 caracteres) |
| `retirement_plan` | objeto |  | Complemento de planes personales de retiro (Planesderetiro 1.1), obligatorio con code 22: lo del año anterior. |
| `retirement_plan.financial_system` | boolean | sí | true si el plan es del sistema financiero (SistemaFinanc). |
| `retirement_plan.contributions_last_year` | number o null |  | Aportaciones actualizadas del año anterior (MontTotAportAnioInmAnterior). |
| `retirement_plan.real_interest` | number | sí | Intereses reales devengados o percibidos el año anterior (MontIntRealesDevengAniooInmAnt). (de 0 a ∞) |
| `retirement_plan.early_withdrawals` | boolean | sí | true si hubo retiros antes de cumplir los requisitos de permanencia (HuboRetirosAnioInmAntPer). |
| `retirement_plan.early_withdrawn` | number o null |  | Monto retirado antes de cumplir la permanencia (MontTotRetiradoAnioInmAntPer); obligatorio con early_withdrawals. |
| `retirement_plan.exempt_withdrawn` | number o null |  | Monto exento de lo retirado el año anterior (MontTotExentRetiradoAnioInmAnt). |
| `retirement_plan.excess_withdrawn` | number o null |  | Excedente del monto exento de lo retirado el año anterior (MontTotExedenteAnioInmAnt). |
| `retirement_plan.withdrawals` | boolean | sí | true si hubo retiros el año anterior (HuboRetirosAnioInmAnt). |
| `retirement_plan.withdrawn` | number o null |  | Monto retirado el año anterior (MontTotRetiradoAnioInmAnt); obligatorio con withdrawals. |
| `retirement_plan.reference` | string o null |  | Número de referencia, contrato o cuenta del cliente (NumReferencia). |
| `retirement_plan.contributions` | arreglo de objeto |  | Aportaciones o depósitos (AportacionesODepositos), uno por tipo y hasta tres. (hasta 3) |
| `retirement_plan.contributions[].type` | `a`, `b`, `c` | sí | Tipo de aportación (TipoAportacionODeposito): a (art. 151 fracc. V LISR), b (art. 185 LISR) o c (art. 258 RLISR, con trustee_rfc). |
| `retirement_plan.contributions[].amount` | number | sí | Monto de la aportación o depósito (MontAportODep). (de 0 a ∞) |
| `retirement_plan.contributions[].trustee_rfc` | string o null |  | RFC de la fiduciaria que administra el plan (RFCFiduciaria); obligatorio con el tipo c. |
| `mortgage_interest` | objeto |  | Complemento de intereses reales deducibles por créditos hipotecarios (Intereseshipotecarios 1.0), obligatorio con code 23. |
| `mortgage_interest.financial_institution` | boolean | sí | true si el crédito lo otorgó una institución financiera (CreditoDeInstFinanc). |
| `mortgage_interest.outstanding_balance` | number | sí | Saldo insoluto al 31 de diciembre del año anterior, o a la fecha del contrato si es de este año (SaldoInsoluto). (de 0 a ∞) |
| `mortgage_interest.deductible_proportion` | number o null |  | Proporción deducible del crédito sobre los intereses reales devengados y pagados (PropDeducDelCredit). |
| `mortgage_interest.nominal_accrued` | number o null |  | Intereses nominales devengados (MontTotIntNominalesDev). |
| `mortgage_interest.nominal_accrued_paid` | number o null |  | Intereses nominales devengados y pagados (MontTotIntNominalesDevYPag). |
| `mortgage_interest.real_deductible` | number o null |  | Intereses reales pagados deducibles (MontTotIntRealPagDeduc). |
| `mortgage_interest.contract` | string o null |  | Número de contrato del crédito hipotecario (NumContrato). |
| `financial_derivatives` | objeto |  | Complemento de operaciones financieras derivadas de capital (Operacionesconderivados 1.0), obligatorio con code 24. |
| `financial_derivatives.gain` | number | sí | Ganancia acumulable (MontGanAcum). (de 0 a ∞) |
| `financial_derivatives.loss` | number | sí | Pérdida deducible (MontPerdDed). (de 0 a ∞) |
| `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. |
| `email` | string |  | Correo a donde se envía (varios separados por comas). Solo se usa si se pide enviarlo. (hasta 1000 caracteres) |
| `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
{
  "code": "01",
  "recipient": {
    "tax_id": "PEPJ800101AB1",
    "legal_name": "JUAN PEREZ PEREZ",
    "zip": "33826"
  },
  "period": {
    "year": 2026,
    "month": 9
  },
  "totals": {
    "operation": 10000
  },
  "taxes": [
    {
      "tax": "isr",
      "base": 10000,
      "amount": 1000
    },
    {
      "tax": "iva",
      "base": 10000,
      "amount": 1066.67
    }
  ],
  "metadata": {
    "proveedor": "42"
  }
}
```

## Con el SDK de TypeScript

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

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

const retention = await fiscalisto.retentions.create({
  code: "01",
  recipient: {
    tax_id: "PEPJ800101AB1",
    legal_name: "JUAN PEREZ PEREZ",
    zip: "33826",
  },
  period: { year: 2026, month: 9 },
  totals: { operation: 10000 },
  taxes: [
    { tax: "isr", base: 10000, amount: 1000 },
    { tax: "iva", base: 10000, amount: 1066.67 },
  ],
  metadata: { proveedor: "42" },
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

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

retention = fiscalisto.retentions.create({
    "code": "01",
    "recipient": {
        "tax_id": "PEPJ800101AB1",
        "legal_name": "JUAN PEREZ PEREZ",
        "zip": "33826",
    },
    "period": {"year": 2026, "month": 9},
    "totals": {"operation": 10000},
    "taxes": [
        {
            "tax": "isr",
            "base": 10000,
            "amount": 1000,
        },
        {
            "tax": "iva",
            "base": 10000,
            "amount": 1066.67,
        },
    ],
    "metadata": {"proveedor": "42"},
}, 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();

$retention = $fiscalisto->retentions->create([
    'code' => '01',
    'recipient' => [
        'tax_id' => 'PEPJ800101AB1',
        'legal_name' => 'JUAN PEREZ PEREZ',
        'zip' => '33826',
    ],
    'period' => ['year' => 2026, 'month' => 9],
    'totals' => ['operation' => 10000],
    'taxes' => [
        [
            'tax' => 'isr',
            'base' => 10000,
            'amount' => 1000,
        ],
        [
            'tax' => 'iva',
            'base' => 10000,
            'amount' => 1066.67,
        ],
    ],
    'metadata' => ['proveedor' => '42'],
], ['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 retention = await fiscalisto.Retentions.CreateAsync(new CreateRetentionParams
{
    Code = "01",
    Recipient = new()
    {
        TaxId = "PEPJ800101AB1",
        LegalName = "JUAN PEREZ PEREZ",
        Zip = "33826",
    },
    Period = new() { Year = 2026, Month = 9 },
    Totals = new() { Operation = 10000 },
    Taxes = new()
    {
        new() { Tax = "isr", Base = 10000, Amount = 1000 },
        new()
        {
            Tax = "iva",
            Base = 10000,
            Amount = 1066.67m,
        },
    },
    Metadata = new() { ["proveedor"] = "42" },
}, 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()

	retention, err := client.Retentions.Create(ctx, &fiscalisto.CreateRetentionParams{
		Code: "01",
		Recipient: fiscalisto.CreateRetentionParamsRecipient{
			TaxID:     fiscalisto.String("PEPJ800101AB1"),
			LegalName: "JUAN PEREZ PEREZ",
			Zip:       fiscalisto.String("33826"),
		},
		Period: fiscalisto.CreateRetentionParamsPeriod{
			Year:  2026,
			Month: fiscalisto.Int64(9),
		},
		Totals: fiscalisto.CreateRetentionParamsTotals{Operation: 10000},
		Taxes: []fiscalisto.CreateRetentionParamsTax{
			{Tax: "isr", Base: 10000, Amount: 1000},
			{Tax: "iva", Base: 10000, Amount: 1066.67},
		},
		Metadata: map[string]string{"proveedor": "42"},
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(retention.ID)
}
```

## Con el SDK de Java

```java
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.CreateRetentionParams;
import com.fiscalisto.model.CreateRetentionParamsPeriod;
import com.fiscalisto.model.CreateRetentionParamsRecipient;
import com.fiscalisto.model.CreateRetentionParamsTax;
import com.fiscalisto.model.CreateRetentionParamsTotals;
import java.util.List;
import java.util.Map;

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

var retention = fiscalisto.retentions().create(new CreateRetentionParams()
        .setCode("01")
        .setRecipient(new CreateRetentionParamsRecipient()
                .setTaxId("PEPJ800101AB1")
                .setLegalName("JUAN PEREZ PEREZ")
                .setZip("33826"))
        .setPeriod(new CreateRetentionParamsPeriod().setYear(2026).setMonth(9))
        .setTotals(new CreateRetentionParamsTotals().setOperation(10000))
        .setTaxes(List.of(
                new CreateRetentionParamsTax()
                        .setTax("isr")
                        .setBase(10000)
                        .setAmount(1000),
                new CreateRetentionParamsTax()
                        .setTax("iva")
                        .setBase(10000)
                        .setAmount(1066.67)
        ))
        .setMetadata(Map.of("proveedor", "42")), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(retention.getId());
```

## Respuesta 201

Correcto. Repetir la solicitud con la misma Idempotency-Key contesta lo mismo, con el mismo status y el encabezado idempotent-replayed: true.

Un objeto `Retention`:

| 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` | `"retention"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor (iss_…). |
| `status` | `processing`, `valid`, `rejected`, `canceled` | sí | processing: el PAC no ha contestado. valid: timbrada. rejected: el SAT o el PAC no la aceptaron (ver error). canceled: cancelada. |
| `uuid` | string o null | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `folio` | integer o null | sí | Folio (Folio). Fiscalisto asigna el siguiente de la serie; mande uno solo si debe ser ese. |
| `internal_folio` | string o null | sí | Folio interno (FolioInt): RET1, RET2… |
| `date` | string o null | sí | Fecha de emisión (Fecha), hora de la Ciudad de México. |
| `code` | string | sí | Clave de la retención (CveRetenc), c_CveRetenc: 01 servicios profesionales, 05 arrendamiento, 14 dividendos, 16 intereses, 18 pagos al extranjero… Las claves 14, 16, 17 y 18 a 24 llevan su complemento (dividends, interest, trust_lease, foreign_payment, share_sale, prize, trust, retirement_plan, mortgage_interest, financial_derivatives); la 26 (plataformas tecnológicas) aún no se puede emitir. |
| `description` | string o null | sí | Descripción de la retención (DescRetenc). |
| `recipient` | objeto | sí | Receptor de la constancia (Receptor): nacional con RFC y código postal, o extranjero. |
| `recipient.foreign` | boolean | sí | true si el receptor es extranjero (sin RFC). |
| `recipient.tax_id` | string o null | sí | RFC (Rfc), 12 caracteres una persona moral y 13 una física. |
| `recipient.legal_name` | string o null | sí | Nombre o razón social tal como está en la constancia de situación fiscal, sin el régimen de capital (sin «S.A. de C.V.»). |
| `recipient.zip` | string |  | Código postal del domicilio fiscal, 5 dígitos, como en la constancia de situación fiscal. El de un emisor es el lugar de expedición (LugarExpedicion) de sus comprobantes. |
| `recipient.curp` | string o null |  | CURP, 18 caracteres. |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.year` | integer | sí | Año (Ejercicio). (de -9007199254740991 a 9007199254740991) |
| `period.from_month` | integer | sí | Mes inicial (MesIni), 1 a 12. (de -9007199254740991 a 9007199254740991) |
| `period.to_month` | integer | sí | Mes final (MesFin), 1 a 12, del mismo año. (de -9007199254740991 a 9007199254740991) |
| `totals` | objeto | sí | Totales (Totales). |
| `totals.operation` | number o null | sí | Monto total de la operación (MontoTotOperacion). |
| `totals.taxed` | number o null | sí | Monto gravado (MontoTotGrav). Por omisión, operation menos exempt. |
| `totals.exempt` | number o null | sí | Monto exento (MontoTotExent). Por omisión 0. |
| `totals.withheld` | number o null | sí | Total retenido (MontoTotRet). |
| `taxes` | arreglo de objeto | sí | Impuestos del comprobante, por tipo. |
| `taxes[].tax` | string | sí | Impuesto: isr, iva o ieps (ImpuestoRet 001, 002, 003). |
| `taxes[].base` | number | sí | Base del impuesto retenido (BaseRet). |
| `taxes[].amount` | number | sí | Monto retenido (MontoRet). |
| `taxes[].payment_type` | string | sí | Tipo de pago de la retención (TipoPagoRet): 01 definitivo IVA, 02 definitivo IEPS, 03 definitivo ISR, 04 provisional ISR. Por omisión el usual de cada impuesto. |
| `dividends` | objeto |  | Complemento de dividendos. |
| `interest` | objeto |  | Complemento de intereses. |
| `foreign_payment` | objeto |  | Complemento de pagos a extranjeros. |
| `trust_lease` | objeto |  | Complemento de arrendamiento en fideicomiso (Arrendamientoenfideicomiso 1.0), obligatorio con code 17. |
| `share_sale` | objeto |  | Complemento de enajenación de acciones u operaciones de valores (EnajenaciondeAcciones 1.0), obligatorio con code 19. |
| `prize` | objeto |  | Complemento de premios (Premios 1.0), obligatorio con code 20. Sus montos son los de totals. |
| `trust` | objeto |  | Complemento de fideicomisos que no realizan actividades empresariales (Fideicomisonoempresarial 1.0), obligatorio con code 21. |
| `retirement_plan` | objeto |  | Complemento de planes personales de retiro (Planesderetiro 1.1), obligatorio con code 22: lo del año anterior. |
| `mortgage_interest` | objeto |  | Complemento de intereses reales deducibles por créditos hipotecarios (Intereseshipotecarios 1.0), obligatorio con code 23. |
| `financial_derivatives` | objeto |  | Complemento de operaciones financieras derivadas de capital (Operacionesconderivados 1.0), obligatorio con code 24. |
| `cancellation` | objeto o null | sí | La cancelación, si se pidió: estado, motivo, sustituto y cuándo. |
| `cancellation.status` | string | sí | pending (espera la respuesta del cliente), accepted (cancelada), rejected (el cliente la rechazó) o lapsed (venció; puede pedirla otra vez). |
| `cancellation.motive` | string o null | sí | Motivo de cancelación (c_MotivoCancelacion): 01 con errores con relación (lleva substitution), 02 con errores sin relación (por omisión), 03 no se llevó a cabo, 04 solo en una factura global, cuando una venta incluida se facturó a nombre del cliente. |
| `cancellation.canceled_at` | string (date-time) o null | sí | Cuándo se canceló. |
| `email` | objeto o null | sí | El envío por correo: a quién, con copia a quién y cuándo (null si no se ha enviado). |
| `email.to` | string o null | sí | A quién (correos separados por comas). |
| `email.sent_at` | string (date-time) o null | sí | Cuándo se envió. |
| `error` | objeto o null | sí | Por qué el SAT o el PAC no lo aceptaron: mensaje, código del SAT y texto original. |
| `error.message` | string | sí | Qué pasó y cómo corregirlo, para una persona. |
| `error.sat_code` | string o null | sí | Código del SAT o del PAC (CFDI40xxx). |
| `error.raw` | string | sí | El texto original del PAC. |
| `created_at` | string (date-time) o null | sí | Cuándo se creó, ISO 8601 con la hora de la Ciudad de México (-06:00). |
| `metadata` | objeto | sí | 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. |
| `warnings` | arreglo de string |  | Avisos que no impidieron timbrar (por ejemplo, el XML se guardará después). |
| `email_error` | string |  | Por qué no se pudo mandar el correo; el comprobante sí se timbró. |

```json
{
  "id": "ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv",
  "object": "retention",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "status": "valid",
  "uuid": "9A6F6BF3-6786-4747-800A-C9964E6509AE",
  "folio": 1,
  "internal_folio": "RET1",
  "date": "2026-10-24T10:15:42",
  "code": "01",
  "description": null,
  "recipient": {
    "foreign": false,
    "tax_id": "PEPJ800101AB1",
    "legal_name": "JUAN PEREZ PEREZ",
    "zip": "33826",
    "curp": null
  },
  "period": {
    "year": 2026,
    "from_month": 9,
    "to_month": 9
  },
  "totals": {
    "operation": 10000,
    "taxed": 10000,
    "exempt": 0,
    "withheld": 2066.67
  },
  "taxes": [
    {
      "tax": "isr",
      "base": 10000,
      "amount": 1000,
      "payment_type": "04"
    },
    {
      "tax": "iva",
      "base": 10000,
      "amount": 1066.67,
      "payment_type": "01"
    }
  ],
  "cancellation": null,
  "email": null,
  "error": null,
  "created_at": "2026-10-24T10:15:42-06:00",
  "metadata": {
    "proveedor": "42"
  }
}
```

## Respuesta 202

El PAC no contestó a tiempo: el comprobante queda en processing y se timbra solo en unos momentos. Escuche el evento *.stamped o consúltelo con GET; repetir la solicitud con la misma Idempotency-Key contesta su estado sin timbrar otra vez.

Un objeto `Retention`:

| 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` | `"retention"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor (iss_…). |
| `status` | `processing`, `valid`, `rejected`, `canceled` | sí | processing: el PAC no ha contestado. valid: timbrada. rejected: el SAT o el PAC no la aceptaron (ver error). canceled: cancelada. |
| `uuid` | string o null | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `folio` | integer o null | sí | Folio (Folio). Fiscalisto asigna el siguiente de la serie; mande uno solo si debe ser ese. |
| `internal_folio` | string o null | sí | Folio interno (FolioInt): RET1, RET2… |
| `date` | string o null | sí | Fecha de emisión (Fecha), hora de la Ciudad de México. |
| `code` | string | sí | Clave de la retención (CveRetenc), c_CveRetenc: 01 servicios profesionales, 05 arrendamiento, 14 dividendos, 16 intereses, 18 pagos al extranjero… Las claves 14, 16, 17 y 18 a 24 llevan su complemento (dividends, interest, trust_lease, foreign_payment, share_sale, prize, trust, retirement_plan, mortgage_interest, financial_derivatives); la 26 (plataformas tecnológicas) aún no se puede emitir. |
| `description` | string o null | sí | Descripción de la retención (DescRetenc). |
| `recipient` | objeto | sí | Receptor de la constancia (Receptor): nacional con RFC y código postal, o extranjero. |
| `recipient.foreign` | boolean | sí | true si el receptor es extranjero (sin RFC). |
| `recipient.tax_id` | string o null | sí | RFC (Rfc), 12 caracteres una persona moral y 13 una física. |
| `recipient.legal_name` | string o null | sí | Nombre o razón social tal como está en la constancia de situación fiscal, sin el régimen de capital (sin «S.A. de C.V.»). |
| `recipient.zip` | string |  | Código postal del domicilio fiscal, 5 dígitos, como en la constancia de situación fiscal. El de un emisor es el lugar de expedición (LugarExpedicion) de sus comprobantes. |
| `recipient.curp` | string o null |  | CURP, 18 caracteres. |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.year` | integer | sí | Año (Ejercicio). (de -9007199254740991 a 9007199254740991) |
| `period.from_month` | integer | sí | Mes inicial (MesIni), 1 a 12. (de -9007199254740991 a 9007199254740991) |
| `period.to_month` | integer | sí | Mes final (MesFin), 1 a 12, del mismo año. (de -9007199254740991 a 9007199254740991) |
| `totals` | objeto | sí | Totales (Totales). |
| `totals.operation` | number o null | sí | Monto total de la operación (MontoTotOperacion). |
| `totals.taxed` | number o null | sí | Monto gravado (MontoTotGrav). Por omisión, operation menos exempt. |
| `totals.exempt` | number o null | sí | Monto exento (MontoTotExent). Por omisión 0. |
| `totals.withheld` | number o null | sí | Total retenido (MontoTotRet). |
| `taxes` | arreglo de objeto | sí | Impuestos del comprobante, por tipo. |
| `taxes[].tax` | string | sí | Impuesto: isr, iva o ieps (ImpuestoRet 001, 002, 003). |
| `taxes[].base` | number | sí | Base del impuesto retenido (BaseRet). |
| `taxes[].amount` | number | sí | Monto retenido (MontoRet). |
| `taxes[].payment_type` | string | sí | Tipo de pago de la retención (TipoPagoRet): 01 definitivo IVA, 02 definitivo IEPS, 03 definitivo ISR, 04 provisional ISR. Por omisión el usual de cada impuesto. |
| `dividends` | objeto |  | Complemento de dividendos. |
| `interest` | objeto |  | Complemento de intereses. |
| `foreign_payment` | objeto |  | Complemento de pagos a extranjeros. |
| `trust_lease` | objeto |  | Complemento de arrendamiento en fideicomiso (Arrendamientoenfideicomiso 1.0), obligatorio con code 17. |
| `share_sale` | objeto |  | Complemento de enajenación de acciones u operaciones de valores (EnajenaciondeAcciones 1.0), obligatorio con code 19. |
| `prize` | objeto |  | Complemento de premios (Premios 1.0), obligatorio con code 20. Sus montos son los de totals. |
| `trust` | objeto |  | Complemento de fideicomisos que no realizan actividades empresariales (Fideicomisonoempresarial 1.0), obligatorio con code 21. |
| `retirement_plan` | objeto |  | Complemento de planes personales de retiro (Planesderetiro 1.1), obligatorio con code 22: lo del año anterior. |
| `mortgage_interest` | objeto |  | Complemento de intereses reales deducibles por créditos hipotecarios (Intereseshipotecarios 1.0), obligatorio con code 23. |
| `financial_derivatives` | objeto |  | Complemento de operaciones financieras derivadas de capital (Operacionesconderivados 1.0), obligatorio con code 24. |
| `cancellation` | objeto o null | sí | La cancelación, si se pidió: estado, motivo, sustituto y cuándo. |
| `cancellation.status` | string | sí | pending (espera la respuesta del cliente), accepted (cancelada), rejected (el cliente la rechazó) o lapsed (venció; puede pedirla otra vez). |
| `cancellation.motive` | string o null | sí | Motivo de cancelación (c_MotivoCancelacion): 01 con errores con relación (lleva substitution), 02 con errores sin relación (por omisión), 03 no se llevó a cabo, 04 solo en una factura global, cuando una venta incluida se facturó a nombre del cliente. |
| `cancellation.canceled_at` | string (date-time) o null | sí | Cuándo se canceló. |
| `email` | objeto o null | sí | El envío por correo: a quién, con copia a quién y cuándo (null si no se ha enviado). |
| `email.to` | string o null | sí | A quién (correos separados por comas). |
| `email.sent_at` | string (date-time) o null | sí | Cuándo se envió. |
| `error` | objeto o null | sí | Por qué el SAT o el PAC no lo aceptaron: mensaje, código del SAT y texto original. |
| `error.message` | string | sí | Qué pasó y cómo corregirlo, para una persona. |
| `error.sat_code` | string o null | sí | Código del SAT o del PAC (CFDI40xxx). |
| `error.raw` | string | sí | El texto original del PAC. |
| `created_at` | string (date-time) o null | sí | Cuándo se creó, ISO 8601 con la hora de la Ciudad de México (-06:00). |
| `metadata` | objeto | sí | 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. |
| `warnings` | arreglo de string |  | Avisos que no impidieron timbrar (por ejemplo, el XML se guardará después). |
| `email_error` | string |  | Por qué no se pudo mandar el correo; el comprobante sí se timbró. |

```json
{
  "id": "ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv",
  "object": "retention",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "status": "valid",
  "uuid": "9A6F6BF3-6786-4747-800A-C9964E6509AE",
  "folio": 1,
  "internal_folio": "RET1",
  "date": "2026-10-24T10:15:42",
  "code": "01",
  "description": null,
  "recipient": {
    "foreign": false,
    "tax_id": "PEPJ800101AB1",
    "legal_name": "JUAN PEREZ PEREZ",
    "zip": "33826",
    "curp": null
  },
  "period": {
    "year": 2026,
    "from_month": 9,
    "to_month": 9
  },
  "totals": {
    "operation": 10000,
    "taxed": 10000,
    "exempt": 0,
    "withheld": 2066.67
  },
  "taxes": [
    {
      "tax": "isr",
      "base": 10000,
      "amount": 1000,
      "payment_type": "04"
    },
    {
      "tax": "iva",
      "base": 10000,
      "amount": 1066.67,
      "payment_type": "01"
    }
  ],
  "cancellation": null,
  "email": null,
  "error": null,
  "created_at": "2026-10-24T10:15:42-06:00",
  "metadata": {
    "proveedor": "42"
  }
}
```

## Errores

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