factadesarrolladores API 0.1.0-esqueleto

Registrar un evento de retorno

Cuando un cliente devuelve mercadería, se le reembolsa un cobro o se reduce una exportación, el documento original no se toca: se registra un evento de retorno. POST /v1/dte/{codigoGeneracion}/return produce un evento aparte, con su propio documento firmado, su propio código de generación y su propio sello del Ministerio de Hacienda. No gasta correlativo y, una vez sellado, no se deshace.

Se aplica a una factura (01), una factura de exportación (11) o una factura de sujeto excluido (14) con sello, que esta API haya emitido. Para otros tipos de documento la corrección es una nota de crédito.

Varios eventos sobre el mismo documento

Un documento admite tantos eventos de retorno como hagan falta, hasta sumar lo que se vendió. Hacienda lleva esa suma y rechaza el exceso; Facta la lleva también, línea por línea, y se la dice antes de firmar nada. Para saber cuánto queda, consulte el documento:

curlTerminal · lo que queda por devolver
curl "$FACTA_API_BASE_URL/v1/dte/7875BC7A-9580-441D-94E4-FA455E9D8BD0" \
  -H "X-Facta-Key: $FACTA_API_KEY"

La respuesta trae disponible (por cada línea: lo vendida, lo devuelta y lo disponible) y retornos, la lista de eventos ya registrados. Si el documento se emitió desde la app, disponible es null: esta API solo puede registrar eventos de retorno sobre los documentos que ella misma emitió.

El cuerpo: líneas desde 1

curlTerminal · una unidad de la primera línea
curl -X POST "$FACTA_API_BASE_URL/v1/dte/7875BC7A-9580-441D-94E4-FA455E9D8BD0/return" \
  -H "X-Facta-Key: $FACTA_API_KEY" \
  -H "X-Facta-Sign-Key: $FACTA_SIGN_KEY" \
  -H "Idempotency-Key: retorno-venta-00417-a" \
  -H "Content-Type: application/json" \
  -d '{ "items": [ { "linea": 1, "cantidad": 1 } ] }'

Las líneas se cuentan desde 1, como en la factura impresa: linea: 1 es la primera. Cada item lleva una de dos formas, nunca las dos:

CampoQué es
cantidadUnidades que regresan de esa línea. El precio, la descripción y los tributos se copian de la original; si hubo descuento, se prorratea por la parte devuelta.
noGravadoUn cargo (positivo) o un abono (negativo) que no afecta la base imponible. Solo mueve el total a pagar, no puede pasar de lo que traía la línea ni cambiar de signo, y una factura de sujeto excluido no lo admite.

fechaEvento es opcional (AAAA-MM-DD, por defecto hoy en El Salvador). El plazo es de tres meses desde que el documento se generó o se selló, el que venza antes, o de dos años para facturas de ciertas actividades económicas.

Lo que contesta

EstadoQué significa
200Sellado. Trae selloRecibido, totales del evento, jws, archivoJson y el disponible que queda ya contando este evento.
202Hacienda no contestó. Vea la sección siguiente.
409idempotency_in_flight o sign_vault_missing: la misma petición sigue en curso, o la llave no está provisionada para firmar.
422No se pudo registrar. El code dice por qué.

Los códigos de la familia 422:

  • return_exceeds_available: se pide más de lo que queda. details.lineas trae, por cada línea, lo solicitado y lo disponible.
  • return_window_closed: fechaEvento está fuera del plazo.
  • return_type_not_allowed: el documento no es 01, 11 ni 14.
  • validation_failed: el documento no tiene sello, está anulado, o el evento no cumple el esquema oficial.
  • mh_rejected: Hacienda leyó el evento y lo negó. Sus unidades vuelven al saldo.

Cuando Hacienda no contesta

El evento quedó firmado y registrado, y sus unidades ya cuentan como devueltas: se le debe a Hacienda, como se le debe un DTE en contingencia. La respuesta es 202 con estado: "firmado" y el jws que se enviará.

Repita la misma llamada: la misma Idempotency-Key y el mismo cuerpo. Antes de reenviar, la API le pregunta a Hacienda qué guarda de ese evento: si ya lo selló, asienta el sello; si lo rechazó, asienta el rechazo. Solo reenvía el mismo evento firmado cuando Hacienda no tiene registro de él; nunca arma un segundo evento. Con otra Idempotency-Key, en cambio, sería una devolución nueva sobre las mismas unidades, y la API la rechazaría por exceso.

Un documento con eventos de retorno no se anula

Hacienda lo rechaza (Anexo V 44.4), y Facta lo detiene antes: POST …/invalidate contesta 409 has_return_events y no manda nada. Si el documento tiene un error de fondo, corríjalo con más eventos de retorno o con una nota de crédito.

Guardar el archivo

archivoJson son los bytes exactos del JSON del evento: guárdelos tal cual, como guarda el del DTE. El evento también se descarga con su propio código en GET /v1/dte/{codigoGeneracion}/file?kind=json, mientras el área de retención de la API (una hora) o el almacenamiento administrado lo tengan.

La hoja carta del evento viene en la respuesta, en representacionGrafica (PDF en base64), y se descarga con GET …/file?kind=pdf por el código del evento. Pasado el área de retención, Facta rearma el JSON y la hoja de la firma que guarda con cada evento sellado; solo un evento sin firma guardada contesta 404 return_pdf_unavailable, y un evento de retorno no tiene ticket. Para contarlo en sus destinos propios, escríbalo con el código del evento y avíselo en POST /v1/storage/copies/{codigoGeneracion}/byos, igual que un documento.

En código

El SDK de TypeScript lo expone como registerReturn. En los demás lenguajes hay un ejemplo completo de cada uno en sdks/<lenguaje>/examples/retorno.*, con la misma estructura que el de emitir: leer lo que queda, registrar el evento, distinguir 200, 202, 409 y 422, y guardar el JSON.

Otras guías

Escriba para buscar Por ejemplo: idempotencia, contingencia, 422, emitir.

↑ ↓ moverse Enter abrir Esc cerrar