Stamp sealed XML
If your system already builds the CFDI 4.0 XML and seals it with your CSD, send it as is and the API only stamps it. It's the shortest path: you don't have to translate your XML into our JSON.
POST
/invoice/stampxmlPOST
/invoice/stampxmlfileWhen to use it
Use it if your ERP already generates the original string and the seal. If you'd rather send the data and let us build and seal the XML, use Create a CFDI. Both paths use 1 folio per stamped CFDI.
| stampxml / stampxmlfile | create | |
|---|---|---|
| Who builds and seals the XML | Your system, with your CSD. | The API, with the CSD uploaded to your account. |
| Validation before stamping | The stamping provider's and the SAT's. | JSON types, the SAT schema (702) and then the SAT. |
| Shows up in your issued CFDIs | No: it doesn't appear in listings and you can't send it with invoice/send. | Yes. |
Not generated: build your own from XmlBase64. | Yes, with your template. |
Send the XML in Base64
POST
/invoice/stampxmlBody (form)
xmlbase64- The full, sealed CFDI 4.0 XML in standard Base64. URL-encode the form body: an unencoded
+arrives as a space and breaks the XML.
# El XML ya sellado con tu CSD, en Base64 y codificado para el formulario
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')"Send the XML as a file
POST
/invoice/stampxmlfileBody (multipart/form-data)
xml- The sealed CFDI
.xmlfile, up to 40 MB. Let your HTTP client setContent-Type: multipart/form-datawith itsboundary; if you set it by hand as a plain form, the file doesn't arrive.
curl -sS -X POST "$FD_API/invoice/stampxmlfile" \
-H "X-Api-Key: $FD_API_KEY" \
-F "xml=@factura-sellada.xml"The response
Both paths respond the same way. The full stamped XML comes in cfdi.XmlBase64: store it, it's your voucher.
{
"message": "XML stamped successfully",
"code": 200,
"cfdi": {
"NoCertificado": "30001000000500003416",
"UUID": "6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13",
"FechaTimbrado": "2026-11-03T10:15:30",
"RfcProvCertif": "AAA010101AAA",
"SelloCFD": "Q2V4...Zm9vYmFy",
"NoCertificadoSAT": "30001000000500003456",
"SelloSAT": "Tm9w...ZGF0YQ==",
"CadenaOrigTFD": "||1.1|6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13|2026-11-03T10:15:30|AAA010101AAA|Q2V4...Zm9vYmFy|30001000000500003456||",
"CadenaQR": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=6F0C2E1A-…",
"XmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4...",
"PDF": "https://app.facturadigital.com.mx/docs/pdf/6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13",
"XML": "https://app.facturadigital.com.mx/docs/xml/EKU9003173C9/6F0C2E1A-9B3D-4C7E-8A51-2D4F6B8C0E13"
}
}CadenaOrigTFDis the original string of the digital tax stamp, for your PDF.CadenaQRis the SAT verification URL for your PDF's QR code.XMLdownloads the stamped XML as long as the issuer RFC in the XML is your account's.PDFisn't generated for an XML stamped this way; build your printed version fromXmlBase64.
Errors
| code | When | What to do |
|---|---|---|
| 400 | xmlbase64 (or the xml file) is missing, or the file isn't .xml. | Check the field name and the body type. |
| 400 + SAT key | The SAT or the provider rejected the XML: seal, schema or a matrix rule. The key goes at the start of message. | Look it up in the error matrix and fix the XML. |
400 + timbre_previo | That same XML was already stamped. context.uuid carries the UUID and no extra folio is charged. | Use that UUID; don't send it again. |
| 601 | Your account has no folios. | Buy folios. |
| 5037 | The API couldn't connect to the stamping provider; nothing was sent. | Retry as is in a few minutes. |
| 5034 | The provider didn't respond in time: the CFDI may have been stamped. | Don't resend blindly. If context.uuid is there, that's your UUID; if not, check with the SAT before you retry. |
Checked against the production API v5 on 2026-11-03.