Skip to content
On this page

Cancelación por UUID ​

Cancela un CFDI directamente por su UUID, sin enviar tus Certificados de Sello Digital en la petición. Timbra resuelve la firma con el CSD configurado en tu cuenta.

Tienes dos variantes del mismo servicio:

  • Con un cuerpo JSON.
  • Con los parámetros en la ruta de la URL.

Variante 1: JSON ​

POST/api/masivo/cfdi33/cancel/uuid

Cancela un CFDI por UUID enviando un objeto JSON.

Auth: BearerContent-Type: application/jsonConsume timbre: No

Request ​

CampoTipoObligatorioDescripción
uuidstringSíUUID del CFDI que quieres cancelar.
motivostringNoMotivo de cancelación del SAT. Por defecto 03.
folio_sustitutostringCondicionalUUID del CFDI sustituto. Obligatorio cuando motivo es 01.
rfcstringNoRFC del emisor. Si se omite, se usa el RFC asociado a la API Key.
json
{
  "uuid": "A1B2C3D4-5E6F-7890-ABCD-EF1234567890",
  "motivo": "02",
  "folio_sustituto": ""
}

Ejemplo ​

bash
curl -X POST "https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/uuid" \
  -H "Authorization: Bearer tmb_live_tu_api_key_aqui" \
  -H "Content-Type: application/json" \
  -d '{
    "uuid": "A1B2C3D4-5E6F-7890-ABCD-EF1234567890",
    "motivo": "02",
    "folio_sustituto": ""
  }'
js
const response = await fetch(
  'https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/uuid',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.TIMBRA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      uuid: 'A1B2C3D4-5E6F-7890-ABCD-EF1234567890',
      motivo: '02',
      folio_sustituto: ''
    })
  }
)

const result = await response.json()

if (!response.ok) {
  throw new Error(result.message)
}

console.log('Acuse:', result.data.acuse)
python
import os
import requests

response = requests.post(
    "https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/uuid",
    headers={
        "Authorization": f"Bearer {os.environ['TIMBRA_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "uuid": "A1B2C3D4-5E6F-7890-ABCD-EF1234567890",
        "motivo": "02",
        "folio_sustituto": "",
    },
)

result = response.json()

if response.status_code != 200:
    raise Exception(result["message"])

print("Acuse:", result["data"]["acuse"])

Variante 2: parámetros en la URL ​

POST/api/masivo/cfdi33/cancel/:rfc/:uuid/:motivo/:folioSustituto?

Cancela un CFDI por UUID con los datos en la ruta.

Parámetros ​

ParámetroObligatorioDescripción
rfcSíRFC del emisor del CFDI.
uuidSíUUID del CFDI que quieres cancelar.
motivoSíMotivo de cancelación del SAT (01, 02, 03 o 04).
folioSustitutoCondicionalUUID del CFDI sustituto. Obligatorio cuando el motivo es 01.

Ejemplo ​

http
POST /api/masivo/cfdi33/cancel/EKU9003173C9/A1B2C3D4-5E6F-7890-ABCD-EF1234567890/02
bash
curl -X POST "https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/EKU9003173C9/A1B2C3D4-5E6F-7890-ABCD-EF1234567890/02" \
  -H "Authorization: Bearer tmb_test_tu_api_key_aqui"
js
const rfc = 'EKU9003173C9'
const uuid = 'A1B2C3D4-5E6F-7890-ABCD-EF1234567890'
const motivo = '02'

const response = await fetch(
  `https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/${rfc}/${uuid}/${motivo}`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.TIMBRA_API_KEY}`
    }
  }
)

const result = await response.json()

if (!response.ok) {
  throw new Error(result.message)
}

console.log('Acuse:', result.data.acuse)
python
import os
import requests

rfc = "EKU9003173C9"
uuid = "A1B2C3D4-5E6F-7890-ABCD-EF1234567890"
motivo = "02"

response = requests.post(
    f"https://dashboard.timbra.com.mx/api/masivo/cfdi33/cancel/{rfc}/{uuid}/{motivo}",
    headers={"Authorization": f"Bearer {os.environ['TIMBRA_API_KEY']}"},
)

result = response.json()

if response.status_code != 200:
    raise Exception(result["message"])

print("Acuse:", result["data"]["acuse"])

Para incluir un folio sustituto, agrega el UUID al final de la ruta:

http
POST /api/masivo/cfdi33/cancel/EKU9003173C9/A1B2C3D4-5E6F-7890-ABCD-EF1234567890/01/B2C3D4E5-6F70-8901-BCDE-F23456789012

Response ​

Ambas variantes responden con la misma estructura:

json
{
  "status": "success",
  "data": {
    "msg": "Se ha cancelado correctamente",
    "uuid": "A1B2C3D4-5E6F-7890-ABCD-EF1234567890",
    "acuse": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Acuse ...>"
  }
}

data.acuse contiene el acuse de cancelación en XML.

Errores ​

HTTPCausa
400Falta uuid o algún parámetro obligatorio de la ruta.
400El motivo no es válido o falta el folio sustituto cuando el motivo es 01.
400El RFC del emisor no es un RFC de prueba válido en Sandbox.
400El SAT o el PAC rechazaron la cancelación. El detalle viene en message.
401La API Key falta, es inválida o fue revocada.
500Error interno al procesar la cancelación.

Ejemplo cuando falta el UUID:

json
{
  "status": "error",
  "message": "El parámetro \"uuid\" es requerido."
}

Notas ​

  • La cancelación no consume timbres.
  • En modo Test, el RFC del emisor debe ser uno de los RFCs de prueba del SAT. Consulta Ambientes Live y Test.
  • El RFC de la ruta o del body debe coincidir con el emisor del CFDI.
  • Si necesitas firmar con certificados que no están configurados en tu cuenta, usa Cancelación por CSD.
  • Guarda el acuse de cancelación como comprobante de la operación.