# Enviar por correo

`POST https://api.fiscalisto.com/v1/retentions/{id}/send`

Manda el PDF y el XML de la constancia a los correos de to (o al que se dio al timbrarla). Dos envíos a la vez de la misma constancia: el segundo contesta email_failed.

## Parámetros

| Nombre | Dónde | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `id` | ruta | sí | El id del objeto. |
| `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 |
| --- | --- | --- | --- |
| `to` | string |  | A quién (correos separados por comas). (hasta 1000 caracteres) |

Ejemplo:

```json
{
  "to": "juan@example.com"
}
```

## 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.send("ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv", { to: "juan@example.com" }, { 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.send("ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv", {"to": "juan@example.com"}, 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->send('ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv', ['to' => 'juan@example.com'], ['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.SendAsync("ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv", new SendRetentionParams { To = "juan@example.com" }, 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.Send(ctx, "ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv", &fiscalisto.SendRetentionParams{
		To: fiscalisto.String("juan@example.com"),
	}, 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.SendRetentionParams;

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

var retention = fiscalisto.retentions().send("ret_OufpKqnrvx9p5tENFcmUXpXJ58XxnF67kv", new SendRetentionParams().setTo("juan@example.com"), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(retention.getId());
```

## Respuesta 200

Correcto.

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, 403, 404, 429, 500 con el cuerpo de error de siempre; cada código está en https://fiscalisto.com/docs/api/errores.md.
