Fac-360

SIRE

RVIE y RCE, por qué mirar y comprometer son rutas distintas, y por qué no hay dónde ensayar.

El Sistema Integrado de Registros Electrónicos de SUNAT: el registro de ventas (RVIE) y el de compras (RCE) de un contribuyente, mes a mes.

Es otra SUNAT que la de emisión, y conviene saberlo antes de empezar: REST en vez de SOAP, OAuth2 en vez de certificado, ticket en vez de CDR, y el periodo en vez del comprobante. La frontera de firma no participa en nada de esto.

No hay entorno de ensayo. SUNAT no publica un SIRE de pruebas — los manuales v22 nombran dos hosts de servicio y ninguna variante de pruebas. El e-beta.sunat.gob.pe que aparece al buscar es el beta de emisión, otro producto. La primera vez que ejecutes el camino completo será sobre el periodo real de un contribuyente real, y por eso todo lo de abajo insiste tanto.

Antes de nada: la empresa tiene que estar en producción

SIRE sólo conoce RUC reales. Una empresa que todavía emite en BETA no puede tener ni una fila de SIRE: lo rechaza la base de datos, no una comprobación en la ruta.

{ "error": { "code": "SIRE_REQUIRES_PRODUCTION" } }

Pásala a producción primero. En la consola es «Pasar a producción».

Y unas credenciales que no son las de siempre

SIRE usa el mismo par client_id / client_secret que la consulta de validez de CPE, y los cambia por un token de forma distinta: /clientessol/ con password, que identifica a la aplicación y a la persona —RUC, usuario SOL y clave—, frente al /clientesextranet/ con client_credentials de CPE, que identifica sólo a la aplicación.

Hay un requisito que no es nuestro y no podemos modelar. Al crear las credenciales en el portal de SUNAT, el contribuyente registra una aplicación y marca las URI que va a consumir. Tiene que estar marcada «MIGE RCE y RVIE - SIRE». Una aplicación registrada en su día sólo para consultar CPE no la tiene, y su par no servirá aquí por bien guardado que esté. Es una propiedad de lo que alguien marcó en un portal, no de tus datos.

El ciclo de un periodo

abrir → ver propuesta → aceptar y generar → esperar ticket → registrado
EstadoQué significa
PENDINGAbierto. No se ha pedido nada a SUNAT
PROPOSAL_READYLa propuesta se descargó y está para revisar
ACCEPTEDSe aceptó la propuesta
AWAITING_TICKETSUNAT está procesando; hay ticket
REGISTEREDEl registro quedó generado
FAILEDSUNAT dijo que no, con código
AMBIGUOUSNo se puede saber si SUNAT aplicó el último acto

Abrir no manda nada

curl -X POST https://apifact.fac-360.com/api/v2/sire/periods/rvie/202607 \
  -H "Authorization: Bearer $APIFACT_TOKEN"

El libro va como palabra —rvie o rce— y no como los códigos 140000 y 080000 de SUNAT. La traducción vive dentro, que es donde no se equivoca nadie.

Abrir un periodo es una fila en tu registro diciendo que alguien va a trabajar sobre ese mes. Le basta el scope sire:read: exigir sire:manage para esto haría imposible mirar sin tener además la capacidad de cerrar un periodo.

Mirar y comprometer son rutas distintas

# MIRAR: descarga la propuesta de SUNAT y para.            scope sire:read
curl -X POST .../sire/periods/rvie/202607/proposal -H "Authorization: Bearer $T"

# COMPROMETER: acepta la propuesta y genera el registro.    scope sire:manage
curl -X POST .../sire/periods/rvie/202607/generation -H "Authorization: Bearer $T"

No es la misma ruta con una bandera, y eso es deliberado. La diferencia entre mirar y comprometer no puede vivir en un campo JSON: el día que alguien deje ese campo puesto, un periodo queda cerrado y no hay operación inversa — ninguna ruta de esta plataforma retira un registro generado. Es el mismo razonamiento que hizo de POST /api/v2/documents/validations una ruta y no un dry-run.

Las dos contestan 202 y entregan el periodo a un ciclo durable. El resultado se consulta en GET /api/v2/sire/periods/{book}/{period}.

Una llamada repetida no duplica nada: el identificador de la instancia es el de la operación, así que pedir dos veces la misma ejecución produce una.

AMBIGUOUS es terminal, y no es un error del que se reintente

Es el estado que más importa entender.

No significa que fallara. Significa que no se puede establecer si SUNAT aplicó el último acto — un fallo de transporte sobre una llamada que cambia el periodo, o un 2xx cuyo ticket no se pudo leer. El registro puede haber arrancado, y no hay forma de preguntar por un ticket cuyo número no tenemos.

Volver a ejecutarlo podría generar el registro dos veces, y eso no se deshace. Así que:

  • la plataforma no reintenta jamás un periodo en este estado;
  • la consola no ofrece ningún botón para él;
  • lo resuelve una persona, mirando en SUNAT qué ocurrió de verdad.

Un rechazo con código de SUNAT es otra cosa: eso es FAILED, con el código guardado, porque «falló» no le sirve a nadie y 1033 sí.

Desde la consola

En SIRE, con rol ADMIN — el mismo tramo que los scopes, para que el rol de una persona y el permiso de una credencial no puedan discrepar sobre quién cierra un periodo.

La pantalla mantiene la separación en dos botones: «Ver propuesta» y «Generar». Y generar pide escribir el periodo a mano antes de confirmar. No es fricción decorativa: es la única acción de la consola que no tiene vuelta atrás y que además no tiene dónde ensayarse.

Lo que todavía no hace

  • Contrastar la propuesta de RCE con tus compras reales. La propuesta la arma SUNAT con lo que otros emitieron contra tu RUC, así que el flujo normal no te exige cargar nada. Comparar eso con tus compras es valor añadido y aún no está.
  • Cargar ajustes y no domiciliados, que van por TUS y no por POST.

On this page