¿Migras de PAC? Utiliza stampxml
Si tu sistema ya genera y sella el XML del CFDI 4.0, puedes migrar a Factura Digital sin reescribir esa parte. Envías el mismo XML sellado a invoice/stampxml o invoice/stampxmlfile y la API lo timbra. Esta guía describe los cambios en tu integración y cómo probarlos en el sandbox antes de usar tu certificado de producción.
/invoice/stampxml/invoice/stampxmlfileQué se conserva y qué cambia
| En tu integración | |
|---|---|
| Generación del XML y cadena original | Se conservan. Tu sistema sigue generando el CFDI 4.0 conforme al Anexo 20 del SAT. |
| Sello con tu CSD | Se conserva. No necesitas cargar tu CSD en la cuenta para timbrar. |
| URL y autenticación | Cambian. Las peticiones van a la API v5 con el encabezado X-Api-Key; los detalles están en Llave y ambientes. |
| Envío del XML | Cambia. El XML viaja en Base64 en el campo xmlbase64 (stampxml) o como archivo en el campo xml de una petición multipart (stampxmlfile). |
| Respuesta | Cambia. Es un JSON con el UUID, los datos del timbre y el XML timbrado completo en cfdi.XmlBase64. |
| PDF y envío por correo | Se conservan en tu sistema. stampxml no genera PDF, y el CFDI no aparece en los listados de tu cuenta ni se envía con invoice/send. |
| Cancelación | Se realiza con invoice/cancelwithcsd, enviando tu CSD en la petición. Consulta la guía de cancelación. |
Pasos de la migración
1. Crea tu cuenta de sandbox
El sandbox es gratuito y usa la misma API que producción. Obtén la llave de API de tu cuenta de sandbox y configúrala con la URL base del sandbox, como se describe en Llave y ambientes.
2. Prueba la conexión con un XML de prueba
Genera un XML sellado en el generador de XML de prueba y envíalo a invoice/stampxml del sandbox. Una respuesta HTTP 200 confirma que la llave, la URL y el formato de envío son correctos. El generador incluye los comandos de envío con el nombre del archivo descargado.
3. Comprueba el sellado de tu sistema
Genera un XML con la opción «Sin sello», descarga el .cer y la .key del emisor de prueba y sella el XML con tu código. Después revísalo en el validador de XML, que recalcula la cadena original con la XSLT del SAT e indica si el sello corresponde. De esta forma confirmas que tu sistema sella correctamente antes de instalar tu certificado de producción.
4. Cambia la llamada de timbrado
Sustituye la llamada a tu proveedor actual por la petición a invoice/stampxml. FD_API es la URL base del ambiente y FD_API_KEY, la llave de API de la cuenta. Para enviar el archivo sin codificarlo, usa invoice/stampxmlfile con el campo xml.
curl -sS -X POST "$FD_API/invoice/stampxml" \
-H "X-Api-Key: $FD_API_KEY" \
--data-urlencode "xmlbase64=$(base64 < factura-sellada.xml | tr -d '\n')"<?php
$xml = file_get_contents('factura-sellada.xml');
$ch = curl_init(getenv('FD_API') . '/invoice/stampxml');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('FD_API_KEY')],
CURLOPT_POSTFIELDS => http_build_query(['xmlbase64' => base64_encode($xml)]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
$r = json_decode(curl_exec($ch), true);
echo $r['code'], ' ', $r['cfdi']['UUID'] ?? $r['message'], PHP_EOL;import { readFile } from "node:fs/promises";
const xml = await readFile("factura-sellada.xml");
const res = await fetch(`${process.env.FD_API}/invoice/stampxml`, {
method: "POST",
headers: { "X-Api-Key": process.env.FD_API_KEY },
body: new URLSearchParams({ xmlbase64: xml.toString("base64") }),
signal: AbortSignal.timeout(120_000),
});
const r = await res.json();
console.log(r.code, r.cfdi?.UUID ?? r.message);import base64, os, requests
with open("factura-sellada.xml", "rb") as f:
xml = f.read()
r = requests.post(
f"{os.environ['FD_API']}/invoice/stampxml",
headers={"X-Api-Key": os.environ["FD_API_KEY"]},
data={"xmlbase64": base64.b64encode(xml).decode()},
timeout=120,
)
print(r.json())var xml = await File.ReadAllBytesAsync("factura-sellada.xml");
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) };
http.DefaultRequestHeaders.Add("X-Api-Key", Environment.GetEnvironmentVariable("FD_API_KEY"));
var body = new FormUrlEncodedContent(new Dictionary<string, string> {
["xmlbase64"] = Convert.ToBase64String(xml),
});
var res = await http.PostAsync($"{Environment.GetEnvironmentVariable("FD_API")}/invoice/stampxml", body);
Console.WriteLine(await res.Content.ReadAsStringAsync());5. Adapta la lectura de la respuesta
Ambos métodos devuelven la misma respuesta. Guarda el XML timbrado de cfdi.XmlBase64, que es el comprobante con el TimbreFiscalDigital.
{
"message": "XML stamped successfully",
"code": 200,
"cfdi": {
"UUID": "6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13",
"FechaTimbrado": "2026-11-04T10:15:30",
"NoCertificado": "30001000000500003416",
"SelloCFD": "Q2V4...Zm9vYmFy",
"NoCertificadoSAT": "30001000000500003456",
"SelloSAT": "Tm9w...ZGF0YQ==",
"RfcProvCertif": "AAA010101AAA",
"CadenaOrigTFD": "||1.1|6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13|2026-11-04T10:15:30|…||",
"CadenaQR": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=6F0C2E1A-…",
"XmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4..."
}
}Campos de cfdi
UUID- Folio fiscal asignado en el timbrado.
XmlBase64- XML timbrado completo en Base64. Es el comprobante que debes guardar.
FechaTimbrado- Fecha y hora del timbrado.
SelloSAT y NoCertificadoSAT- Sello del timbre y número del certificado del SAT, para tu representación impresa.
CadenaOrigTFD- Cadena original del timbre fiscal digital, para tu PDF.
CadenaQR- URL de verificación del SAT para el código QR de tu PDF.
6. Maneja los errores y los reintentos
- HTTP 400 con una clave del SAT al inicio de
messageindica que el XML se rechazó. Consulta la clave en la matriz de errores y corrige el XML. timbre_previoindica que ese XML ya se timbró.context.uuidtrae el UUID original y no se consume otro folio, por lo que no debes reenviarlo.601indica que la cuenta no tiene folios disponibles.5037indica que no se pudo conectar con el servicio de timbrado y no se envió nada. Puedes reintentar la misma petición.5034indica que no hubo respuesta a tiempo y el CFDI pudo haberse timbrado. Sicontext.uuidviene en la respuesta, ese es el UUID; si no, verifica antes de reintentar.- Configura un tiempo de espera de al menos 120 segundos en tu cliente HTTP.
7. Pasa a producción
Cambia la URL base a producción, usa la llave de API de tu cuenta de producción y sella con tu CSD. Cada CFDI timbrado consume un folio; un rechazo no consume folios. La referencia completa de ambos métodos está en Timbrar XML sellado.
Herramientas para la migración
- Generador de XML de prueba
CFDI 4.0 selladoGenera un CFDI 4.0 con un RFC y un CSD de prueba del SAT, sellado o sin sello, con los comandos para enviarlo a stampxml o stampxmlfile. - Validador de XML
Sello y cadena originalVerifica el sello contra la cadena original de la XSLT del SAT, el certificado, la fecha y los importes antes de timbrar. - Matriz de errores
CFDI40xxxTodas las claves de error del SAT y los códigos de la API, con buscador. - Colección de Postman
API v5Cada endpoint de la API listo para probar en el sandbox.
Revisado contra la API v5 en producción el 2026-11-03.