Casas de bolsa
Intermediarios del mercado de valores que informan a sus clientes el resultado de sus operaciones.
El complemento de Enajenación de acciones se agrega al CFDI de Retenciones e Información de Pagos para informar la venta de acciones u operaciones con valores y su resultado: la ganancia o la pérdida. Se timbra con la clave de retención 06 (Enajenación de acciones) o la 19 (Enajenación de acciones u operaciones en bolsa de valores) e informa el contrato de intermediación bajo el cual se realizó la operación.
Quién lo emite
Casas de bolsa
Intermediarios del mercado de valores que informan a sus clientes el resultado de sus operaciones.
Bancos e intermediarios con contrato de intermediación
Instituciones que operan valores por cuenta de sus clientes.
Qué datos lleva
Contrato de intermediación
ContratoIntermediacionEl contrato bajo el cual se realizó la operación.
Ganancia
GananciaEl resultado positivo de la operación.
Pérdida
PerdidaEl resultado negativo de la operación.
¿Inviertes en bolsa? No emites nada: tu casa de bolsa te entrega esta constancia con la ganancia o la pérdida del año, y con ella calculas el impuesto en tu declaración anual.
Ejemplo
Un inversionista vende acciones a través de su casa de bolsa. Al cierre del ejercicio la casa de bolsa emite un CFDI de Retenciones por cada cliente: elige la clave de retención (la 06, o la 19 en operaciones en bolsa de valores), indica el contrato de intermediación y captura la ganancia o la pérdida del periodo.
En bolsa, la persona física paga el 10 % sobre la ganancia neta del ejercicio en su declaración anual (artículo 129 de la LISR); la casa de bolsa le informa el resultado con este comprobante.
Ejemplo de CFDI
emitido para el cliente
Para developers
Si ya tienes tu propio sistema o ERP, puedes timbrar el CFDI de retenciones por enajenación de acciones directamente desde tu software con la API de CFDI de retenciones de Facturama.
$usuario = 'TU_USUARIO_API';
$password = 'TU_PASSWORD_API';
$payload = [
'CveRetenc' => '06',
'FechaExp' => '2026-10-02T09:31:07',
'DescRetenc' => 'No aplica',
'LugarExpRetenc' => '78140',
'Folio' => null,
'Emisor' => [
'RfcEmisor' => 'EKU9003173C9',
'NomDenRazSocE' => 'ESCUELA KEMPER URGATE',
'RegimenFiscalE' => '601',
],
'Receptor' => [
'Nacionalidad' => 'Nacional',
'Nacional' => [
'RfcRecep' => 'CACX7605101P8',
'NomDenRazSocR' => 'XOCHILT CASAS CHAVEZ',
'CurpR' => null,
'DomicilioFiscalR' => '36257',
],
],
'Periodo' => [
'MesIni' => 1,
'MesFin' => 1,
'Ejerc' => 2026,
],
'Totales' => [
'MontoTotOperacion' => 100,
'MontoTotGrav' => 100,
'MontoTotExent' => 0,
'MontoTotRet' => 10,
'ImpRetenidos' => [
[
'BaseRet' => 100,
'Impuesto' => '01',
'MontoRet' => 10,
'TipoPagoRet' => '03',
],
],
],
'Complemento' => [
'EnajenacionDeAcciones' => [
'Version' => '1.0',
'ContratoIntermediacion' => 'Contrato de intermediación bursátil 004512',
'Ganancia' => 100,
'Perdida' => 0,
],
],
];
$ch = curl_init('https://apisandbox.facturama.mx/2/retenciones');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, "$usuario:$password");
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$respuesta = curl_exec($ch);
curl_close($ch);
echo $respuesta;
const usuario = 'TU_USUARIO_API';
const password = 'TU_PASSWORD_API';
const payload = {
CveRetenc: '06',
FechaExp: '2026-10-02T09:31:07',
DescRetenc: 'No aplica',
LugarExpRetenc: '78140',
Folio: null,
Emisor: {
RfcEmisor: 'EKU9003173C9',
NomDenRazSocE: 'ESCUELA KEMPER URGATE',
RegimenFiscalE: '601',
},
Receptor: {
Nacionalidad: 'Nacional',
Nacional: {
RfcRecep: 'CACX7605101P8',
NomDenRazSocR: 'XOCHILT CASAS CHAVEZ',
CurpR: null,
DomicilioFiscalR: '36257',
},
},
Periodo: {
MesIni: 1,
MesFin: 1,
Ejerc: 2026,
},
Totales: {
MontoTotOperacion: 100,
MontoTotGrav: 100,
MontoTotExent: 0,
MontoTotRet: 10,
ImpRetenidos: [
{
BaseRet: 100,
Impuesto: '01',
MontoRet: 10,
TipoPagoRet: '03',
},
],
},
Complemento: {
EnajenacionDeAcciones: {
Version: '1.0',
ContratoIntermediacion: 'Contrato de intermediación bursátil 004512',
Ganancia: 100,
Perdida: 0,
},
},
};
fetch('https://apisandbox.facturama.mx/2/retenciones', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + btoa(`${usuario}:${password}`),
},
body: JSON.stringify(payload),
})
.then((res) => res.json())
.then((data) => console.log(data.Complemento.TimbreFiscalDigital.UUID));
import requests
from requests.auth import HTTPBasicAuth
usuario = 'TU_USUARIO_API'
password = 'TU_PASSWORD_API'
payload = {
'CveRetenc': '06',
'FechaExp': '2026-10-02T09:31:07',
'DescRetenc': 'No aplica',
'LugarExpRetenc': '78140',
'Folio': None,
'Emisor': {
'RfcEmisor': 'EKU9003173C9',
'NomDenRazSocE': 'ESCUELA KEMPER URGATE',
'RegimenFiscalE': '601',
},
'Receptor': {
'Nacionalidad': 'Nacional',
'Nacional': {
'RfcRecep': 'CACX7605101P8',
'NomDenRazSocR': 'XOCHILT CASAS CHAVEZ',
'CurpR': None,
'DomicilioFiscalR': '36257',
},
},
'Periodo': {
'MesIni': 1,
'MesFin': 1,
'Ejerc': 2026,
},
'Totales': {
'MontoTotOperacion': 100,
'MontoTotGrav': 100,
'MontoTotExent': 0,
'MontoTotRet': 10,
'ImpRetenidos': [
{
'BaseRet': 100,
'Impuesto': '01',
'MontoRet': 10,
'TipoPagoRet': '03',
},
],
},
'Complemento': {
'EnajenacionDeAcciones': {
'Version': '1.0',
'ContratoIntermediacion': 'Contrato de intermediación bursátil 004512',
'Ganancia': 100,
'Perdida': 0,
},
},
}
respuesta = requests.post(
'https://apisandbox.facturama.mx/2/retenciones',
json=payload,
auth=HTTPBasicAuth(usuario, password),
)
print(respuesta.json())
String usuario = "TU_USUARIO_API";
String password = "TU_PASSWORD_API";
String credenciales = Base64.getEncoder()
.encodeToString((usuario + ":" + password).getBytes());
String payload = """
{
"CveRetenc": "06",
"FechaExp": "2026-10-02T09:31:07",
"DescRetenc": "No aplica",
"LugarExpRetenc": "78140",
"Folio": null,
"Emisor": {
"RfcEmisor": "EKU9003173C9",
"NomDenRazSocE": "ESCUELA KEMPER URGATE",
"RegimenFiscalE": "601"
},
"Receptor": {
"Nacionalidad": "Nacional",
"Nacional": {
"RfcRecep": "CACX7605101P8",
"NomDenRazSocR": "XOCHILT CASAS CHAVEZ",
"CurpR": null,
"DomicilioFiscalR": "36257"
}
},
"Periodo": {
"MesIni": 1,
"MesFin": 1,
"Ejerc": 2026
},
"Totales": {
"MontoTotOperacion": 100,
"MontoTotGrav": 100,
"MontoTotExent": 0,
"MontoTotRet": 10,
"ImpRetenidos": [
{
"BaseRet": 100,
"Impuesto": "01",
"MontoRet": 10,
"TipoPagoRet": "03"
}
]
},
"Complemento": {
"EnajenacionDeAcciones": {
"Version": "1.0",
"ContratoIntermediacion": "Contrato de intermediación bursátil 004512",
"Ganancia": 100,
"Perdida": 0
}
}
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apisandbox.facturama.mx/2/retenciones"))
.header("Content-Type", "application/json")
.header("Authorization", "Basic " + credenciales)
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
var usuario = "TU_USUARIO_API";
var password = "TU_PASSWORD_API";
var payload = new
{
CveRetenc = "06",
FechaExp = "2026-10-02T09:31:07",
DescRetenc = "No aplica",
LugarExpRetenc = "78140",
Folio = (string?)null,
Emisor = new
{
RfcEmisor = "EKU9003173C9",
NomDenRazSocE = "ESCUELA KEMPER URGATE",
RegimenFiscalE = "601",
},
Receptor = new
{
Nacionalidad = "Nacional",
Nacional = new
{
RfcRecep = "CACX7605101P8",
NomDenRazSocR = "XOCHILT CASAS CHAVEZ",
CurpR = (string?)null,
DomicilioFiscalR = "36257",
},
},
Periodo = new
{
MesIni = 1,
MesFin = 1,
Ejerc = 2026,
},
Totales = new
{
MontoTotOperacion = 100,
MontoTotGrav = 100,
MontoTotExent = 0,
MontoTotRet = 10,
ImpRetenidos = new[]
{
new
{
BaseRet = 100,
Impuesto = "01",
MontoRet = 10,
TipoPagoRet = "03",
},
},
},
Complemento = new
{
EnajenacionDeAcciones = new
{
Version = "1.0",
ContratoIntermediacion = "Contrato de intermediación bursátil 004512",
Ganancia = 100,
Perdida = 0,
},
},
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{usuario}:{password}")));
var response = await client.PostAsJsonAsync("https://apisandbox.facturama.mx/2/retenciones", payload);
Console.WriteLine(await response.Content.ReadAsStringAsync());
require 'net/http'
require 'json'
require 'uri'
usuario = 'TU_USUARIO_API'
password = 'TU_PASSWORD_API'
payload = {
CveRetenc: '06',
FechaExp: '2026-10-02T09:31:07',
DescRetenc: 'No aplica',
LugarExpRetenc: '78140',
Folio: nil,
Emisor: {
RfcEmisor: 'EKU9003173C9',
NomDenRazSocE: 'ESCUELA KEMPER URGATE',
RegimenFiscalE: '601',
},
Receptor: {
Nacionalidad: 'Nacional',
Nacional: {
RfcRecep: 'CACX7605101P8',
NomDenRazSocR: 'XOCHILT CASAS CHAVEZ',
CurpR: nil,
DomicilioFiscalR: '36257',
},
},
Periodo: {
MesIni: 1,
MesFin: 1,
Ejerc: 2026,
},
Totales: {
MontoTotOperacion: 100,
MontoTotGrav: 100,
MontoTotExent: 0,
MontoTotRet: 10,
ImpRetenidos: [
{
BaseRet: 100,
Impuesto: '01',
MontoRet: 10,
TipoPagoRet: '03',
},
],
},
Complemento: {
EnajenacionDeAcciones: {
Version: '1.0',
ContratoIntermediacion: 'Contrato de intermediación bursátil 004512',
Ganancia: 100,
Perdida: 0,
},
},
}
uri = URI.parse('https://apisandbox.facturama.mx/2/retenciones')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri, { 'Content-Type' => 'application/json' })
request.basic_auth(usuario, password)
request.body = payload.to_json
puts http.request(request).body
Antes de timbrar
ERROR 01
Dejar vacía la ganancia o la pérdida
Causa
El complemento pide el resultado de la operación en cualquiera de los dos sentidos.
Solución
Captura el campo que corresponda al resultado; el que no aplica va en 0.
ERROR 02
Informar el monto de la venta como ganancia
Causa
La ganancia es el resultado neto —precio de venta menos comisiones y el costo promedio de adquisición actualizado—, no el importe total vendido.
Solución
Captura solo el resultado de la operación.
ERROR 03
No registrar el contrato de intermediación
Causa
El contrato forma parte de lo que informa el complemento.
Solución
Captura el contrato bajo el que se hizo la operación.
Precio
El módulo se contrata una vez y desbloquea los complementos disponibles. Funciona distinto a los complementos individuales: esto es lo que cambia.
Módulo de Retenciones
$1,650 MXN / año
IVA incluido · vigencia de 12 meses a partir de la compra
Cuando uses los 25 folios incluidos, los que timbres se descuentan de tu suscripción principal.
Dudas
El SAT asigna el complemento a dos claves del catálogo c_CveRetenc: la 06, Enajenación de acciones, y la 19, Enajenación de acciones u operaciones en bolsa de valores. Se usa la que describe la operación.
Principalmente las entidades financieras que actúan como intermediarios del mercado de valores, como las casas de bolsa, que lo entregan a sus clientes con la ganancia o la pérdida de sus operaciones. Fuera de bolsa, el adquirente residente en México le retiene a la persona física, como pago provisional, el 20 % sobre el total de la operación, salvo que el vendedor opte por un pago menor en los términos del Reglamento (artículo 126 de la LISR), y emite el CFDI.
Sí. Desde 2014 el complemento es obligatorio tanto si hay ganancia como si hay pérdida. La pérdida se informa porque la persona puede disminuirla de sus ganancias en bolsa del mismo ejercicio o de los diez siguientes, en los términos del artículo 129 de la Ley del ISR.
En bolsa de valores, las personas físicas pagan el 10 % sobre la ganancia neta del ejercicio y lo declaran en su declaración anual (artículo 129 de la Ley del ISR). Fuera de bolsa, el adquirente residente en México retiene como pago provisional el 20 % sobre el total de la operación (artículo 126). El complemento no calcula el impuesto: documenta el resultado de la operación.
Va incluido en el Módulo de Retenciones: $1,650 MXN al año (IVA incluido), sin cobro adicional por complemento, e incluye 25 folios para timbrar. Cuando los uses, los folios se descuentan de tu plan de Facturación, que debe estar activo. Puedes probarlo antes en el sandbox de Facturama, que no tiene costo ni validez fiscal.
Sí. Cuando una persona moral paga honorarios o arrendamiento a una persona física, el CFDI de ingresos de esta, con la retención desglosada, puede servir como constancia de retención; esa facilidad no aplica a la enajenación de acciones: el intermediario sigue emitiendo el CFDI de Retenciones.
Incluidos en el mismo módulo
Residentes en el extranjero
Retenciones por pagos a residentes en el extranjero sin establecimiento permanente en México. Corresponde a la clave 18 de retención.
Empresas que distribuyen utilidades
Reparto de dividendos o utilidades a personas físicas o morales. Corresponde a la clave 14 de retención.
Rifas, sorteos y concursos
Captura entidad federativa, monto gravado y exento. Corresponde a la clave 20 de retención.
Bancos, fintechs y casas de bolsa
Interés nominal, real y pérdida. Corresponde a la clave 16 de retención.
Solo para API
Marketplaces y apps que integran por API
Retenciones de ISR e IVA a quienes prestan servicios o venden a través de tu plataforma. Corresponde a la clave 26 de retención.