ForgeStack
CFDI 🇲🇽 Español

c_ClaveProdServ: el catálogo del SAT que rompe más CFDIs de lo que crees

Más de 80,000 claves de productos y servicios, publicadas en Excel, actualizadas sin aviso. Te explico por qué poner 01010101 en todo es un error que el SAT ya está detectando — y cómo manejarlo correctamente.

R. Elizondo · · 9 min de lectura

Cada partida de un CFDI 4.0 requiere dos campos de catálogo: c_ClaveProdServ (qué es lo que vendiste) y c_ClaveUnidad (en qué unidad lo mediste). Son campos obligatorios, de catálogo cerrado, con más de 80,000 valores posibles. La mayoría de los proyectos los implementa mal desde el principio — y el problema no aparece hasta que el SAT empieza a auditar.

Qué son estos catálogos y de dónde vienen

El SAT publica un archivo Excel llamado catCFDI.xls con todos los catálogos del complemento de facturación. El catálogo c_ClaveProdServ tiene actualmente más de 82,000 entradas organizadas en capítulos y partidas, siguiendo la nomenclatura del Sistema Armonizado de la OMA (la misma base que usan las aduanas a nivel mundial). El catálogo c_ClaveUnidad está basado en la norma UN/ECE Rec. 20 e incluye unidades de medida para todo: kilogramos, litros, horas de servicio, piezas, licencias de software.

El SAT actualiza este archivo sin calendario fijo. Hay versiones nuevas que agregan o modifican entradas varias veces al año. Si tu aplicación carga los catálogos una sola vez en el setup inicial, puede estar usando datos desactualizados.

Por qué poner 01010101 en todo es un error

La clave 01010101 existe en el catálogo: su descripción es "No existe en el catálogo". El SAT la incluyó expresamente como válvula de escape temporal durante la transición a CFDI 4.0. El problema: muchos sistemas la adoptaron como valor permanente para todo.

El SAT cruzó sus datos y puede detectar exactamente qué RFC está usando 01010101 en el 100% (o cerca) de sus facturas. Ese patrón es una señal de alerta para auditorías automáticas. No es ilegal por sí solo — el campo técnicamente es válido — pero combinado con otros indicadores (volumen alto, conceptos genéricos, receptores concentrados) pone a la empresa en una categoría de mayor escrutinio.

Más allá del riesgo de auditoría: muchos PACs ya tienen reglas propias que rechazan ciertos conceptos con 01010101. Si tu sistema usa esa clave de forma indiscriminada y el PAC la rechaza, el error llega en producción al momento de timbrar.

❌ MAL — valor fijo Descripción del concepto (libre) hardcode 01010101 ⚠ Señal de auditoría / rechazo ✅ BIEN — lookup en catálogo Descripción del concepto (libre) búsqueda en caché 82k entradas locales 43211502 Software de facturación CFDI válido ✓ actualizada vía API
El catálogo tiene 82,000+ entradas. La búsqueda debe ser local con caché — no una consulta en línea por cada factura.

El segundo error: consultar el catálogo del SAT en vivo

Algunos equipos resuelven el problema de los catálogos de la peor manera posible: haciendo una petición HTTP al SAT o a algún servicio de terceros en el momento de generar cada factura para validar o resolver la clave. Esto tiene tres problemas graves:

Los tres patrones de código — y cuál usar

Patrón 1: valor hardcodeado

ConceptoBuilder.php — NO hacer esto
// Hardcodeado para "que funcione" — señal de auditoría
$concepto = [
    'ClaveProdServ' => '01010101',  // ← "No existe en catálogo"
    'ClaveUnidad'   => 'ACT',       // ← "Actividad" (genérico)
    'Descripcion'   => 'Servicios de desarrollo',
    'Cantidad'      => '1',
    'ValorUnitario' => '5000.00',
];

Patrón 2: consulta en vivo al momento de facturar

CatalogoService.php — NO hacer esto
// Consulta HTTP externa en cada factura — frágil y lento
public function buscarClave(string $descripcion): string
{
    $response = $this->httpClient->request('GET',
        'https://tercero-no-oficial.mx/catalogo/buscar',
        ['query' => ['q' => $descripcion]]
    );
    // Si este servicio falla → tu facturación falla
    return $response->toArray()['clave'];
}

Patrón 3: caché local + ForgeStack API

CatalogoService.php — patrón correcto
// Catálogo local: < 15 MB en base de datos, consulta en < 1ms
public function buscarClaveProdServ(string $descripcion): SatCatalogResult
{
    return $this->catalogoRepository->buscarPorDescripcion(
        $descripcion,
        CatalogoTipo::PROD_SERV
    );
}

// Actualización programada — no en el camino de la factura
#[AsScheduledTask('0 3 * * 1')]  // cada lunes a las 3am
public function actualizarCatalogos(): void
{
    $this->forgeStackCfdi->catalogos()->sincronizar();
    // descarga el XLS del SAT, importa cambios incrementales
}
ConceptoBuilder.php — con ForgeStack API
$claveProdServ = $this->catalogo
    ->buscarClaveProdServ('Desarrollo de software a medida');

$concepto = $this->forgeStackCfdi
    ->concepto()
    ->descripcion('Servicios de desarrollo')
    ->claveProdServ($claveProdServ->clave())   // '81112101'
    ->claveUnidad('E48')                        // 'Unidad de servicio'
    ->cantidad(1)
    ->valorUnitario(5000.00)
    ->build();

Cómo encontrar la clave correcta para tu producto o servicio

El catálogo usa la taxonomía del Sistema Armonizado. Las claves para servicios digitales y software están en los capítulos 43 (TI) y 81 (servicios profesionales):

c_ClaveProdServ Descripción en catálogo Cuándo usarla
43232408 Plataformas de facturación en línea SaaS de facturación
43231507 Paquetes de software de contabilidad Software de contabilidad
81112101 Servicios de desarrollo de software Desarrollo a medida
81111501 Consultoría en tecnologías de la información Consultoría TI
43232000 Software de empresa como servicio (SaaS) Suscripciones SaaS
80141601 Servicios de publicidad en internet Digital ads / marketing

Nota: siempre verifica en el catálogo oficial vigente. El SAT puede mover o actualizar descripciones en versiones nuevas del Excel.

El catálogo que se olvida: c_ClaveUnidad

La mayoría de los artículos hablan de c_ClaveProdServ y dejan de lado c_ClaveUnidad. Pero el error más frecuente que veo en proyectos PHP es usar ACT (Actividad) para absolutamente todo, incluyendo productos físicos donde correspondería KGM (kilogramo) o H87 (pieza).

c_ClaveUnidad Descripción Cuándo usarla
E48 Unidad de servicio Servicios digitales, SaaS
ACT Actividad Honorarios, consultoría por proyecto
HUR Hora Servicios por hora (desarrollo, soporte)
H87 Pieza Productos unitarios
KGM Kilogramo Productos por peso
LTR Litro Productos líquidos
A9 Licencia Licencias de software
MO Mes Suscripciones mensuales

Cómo manejar las actualizaciones del catálogo

El SAT actualiza el Excel sin publicar un diff. Si tu sistema tiene los catálogos cargados en base de datos, necesitas una estrategia de sincronización que no rompa facturas en producción cuando hay cambios:

SincronizarCatalogosCommand.php
#[AsCommand('forgestack:catalogos:sincronizar')]
class SincronizarCatalogosCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $resultado = $this->forgeStackCfdi
            ->catalogos()
            ->sincronizar([
                'solo_cambios'      => true,  // importación incremental
                'marcar_obsoletos'  => true,  // no borra — marca inactivos
                'notificar_cambios' => true,  // log auditable de qué cambió
            ]);

        $output->writeln(sprintf(
            'Catálogo actualizado: %d nuevas, %d modificadas, %d obsoletas',
            $resultado->nuevas(),
            $resultado->modificadas(),
            $resultado->obsoletas()
        ));

        return Command::SUCCESS;
    }
}
📋

Catálogo SAT precargado. Cero parsing.

Ver ForgeStack CFDI

Resumen: qué hacer y qué no hacer

No hacer

  • Hardcodear 01010101 como clave universal
  • Consultar el catálogo vía HTTP en el path de la factura
  • Usar ACT para productos físicos
  • Cargar el catálogo una sola vez y nunca actualizarlo
  • Confiar en un tercero no oficial para resolución de claves

Hacer

  • Cargar el catálogo completo en base de datos local
  • Actualización incremental programada (no en el path de la factura)
  • Marcar obsoletos en lugar de borrar (no rompe facturas históricas)
  • Mapeo por categoría de producto, no búsqueda de texto libre
  • Auditar qué claves usa tu sistema en producción periódicamente
ForgeStack · Investigación de producto

¿Conciliar pagos SPEI a mano cada mes?

Estamos construyendo una herramienta para automatizar la conciliación de pagos SPEI en despachos y negocios mexicanos. Antes de construirla, queremos entender bien el problema — 4 preguntas, 2 minutos.

Sin compromiso, sin dejar tus datos.

Responder la encuesta