Guía por stack React · Vue · Angular · Svelte Backend intermedio

Cómo consultar y mostrar facturas electrónicas desde React, Vue, Angular o Svelte sin exponer tu API key

Si llamas a la API de facturación directo desde el navegador, tu API key queda a la vista de cualquiera. La solución es un backend intermedio. Aquí el patrón y un ejemplo para React, Vue, Angular y Svelte.

LO QUE VAS A HACER7 pasos

  1. Entiende por qué no llamar a la API desde el navegador
  2. Crea el backend intermedio
  3. Consúmelo desde React
  4. Consúmelo desde Vue
  5. Consúmelo desde Angular
  6. Consúmelo desde Svelte
  7. Protege tu backend

Antes de empezar

Un backend propio

El ejemplo usa Node y Express, pero sirve cualquiera.

Tu API key de pruebas de Flashpi

Solicítala aquí

Paso 1 · Entiende por qué no llamar a la API desde el navegador

Todo lo que corre en el navegador es visible: cualquiera puede abrir las herramientas de desarrollo y copiar tu API key. Con esa key podrían emitir comprobantes a tu nombre.

La API key solo vive en tu servidor. El navegador habla con tu backend, y tu backend habla con Flashpi.

Paso 2 · Crea el backend intermedio

jsserver.mjs
// server.mjs
import express from "express";

const app = express();
app.use(express.json());

const BASE_URL = "https://api.flashpi.ec/v1";
const API_KEY = process.env.FLASHPI_API_KEY; // vive solo en el servidor

app.get("/api/facturas/:claveAcceso", async (req, res) => {
  // Aquí valida que el usuario autenticado tenga permiso sobre esta factura.
  try {
    const r = await fetch(
      `${BASE_URL}/comprobantes/${encodeURIComponent(req.params.claveAcceso)}`,
      { headers: { Authorization: `Bearer ${API_KEY}` } }
    );
    const data = await r.json();
    // Devuelve solo lo que el navegador necesita
    res.status(r.status).json({ estado: data.estado, clave_acceso: data.clave_acceso });
  } catch (err) {
    res.status(502).json({ error: "No se pudo consultar el comprobante" });
  }
});

app.listen(3000, () => console.log("Backend en http://localhost:3000"));

Instala y ejecuta: npm install express y FLASHPI_API_KEY=... node server.mjs.

Paso 3 · Consúmelo desde React

jsxEstadoFactura.jsx
// EstadoFactura.jsx
import { useEffect, useState } from "react";

export function EstadoFactura({ claveAcceso }) {
  const [estado, setEstado] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(`/api/facturas/${claveAcceso}`)
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`Error ${r.status}`))))
      .then(setEstado)
      .catch((e) => setError(e.message));
  }, [claveAcceso]);

  if (error) return <p>No se pudo consultar: {error}</p>;
  if (!estado) return <p>Consultando…</p>;
  return <p>Estado: {estado.estado}</p>;
}

Paso 4 · Consúmelo desde Vue

vueEstadoFactura.vue
<!-- EstadoFactura.vue -->
<script setup>
import { ref, onMounted } from "vue";

const props = defineProps({ claveAcceso: String });
const estado = ref(null);
const error = ref(null);

onMounted(async () => {
  try {
    const r = await fetch(`/api/facturas/${props.claveAcceso}`);
    if (!r.ok) throw new Error(`Error ${r.status}`);
    estado.value = await r.json();
  } catch (e) {
    error.value = e.message;
  }
});
</script>

<template>
  <p v-if="error">No se pudo consultar: {{ error }}</p>
  <p v-else-if="!estado">Consultando…</p>
  <p v-else>Estado: {{ estado.estado }}</p>
</template>

Paso 5 · Consúmelo desde Angular

tsfacturas.service.ts
// facturas.service.ts
import { Injectable, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Injectable({ providedIn: "root" })
export class FacturasService {
  private http = inject(HttpClient);

  estado(claveAcceso: string) {
    return this.http.get<{ estado: string }>(`/api/facturas/${claveAcceso}`);
  }
}

Recuerda registrar provideHttpClient() en la configuración de tu aplicación.

Paso 6 · Consúmelo desde Svelte

svelteEstadoFactura.svelte
<!-- EstadoFactura.svelte -->
<script>
  export let claveAcceso;

  const consulta = fetch(`/api/facturas/${claveAcceso}`).then((r) => {
    if (!r.ok) throw new Error(`Error ${r.status}`);
    return r.json();
  });
</script>

{#await consulta}
  <p>Consultando…</p>
{:then estado}
  <p>Estado: {estado.estado}</p>
{:catch error}
  <p>No se pudo consultar: {error.message}</p>
{/await}

Este ejemplo usa la sintaxis de Svelte 3 y 4, que también funciona en Svelte 5.

Paso 7 · Protege tu backend

  • Autentica a tus usuarios y verifica que cada uno solo vea sus facturas.
  • Devuelve al navegador solo los campos necesarios.
  • Configura CORS para aceptar solo tu dominio.
  • Limita la cantidad de solicitudes por usuario.

Errores frecuentes

SíntomaCausa probableQué hacerReferencia
401 UnauthorizedAPI key ausente, inválida o de otro ambiente.Revisa el header Authorization y que uses la key del ambiente correcto.Ver detalle
SRI 70Clave de acceso en procesamiento.Espera unos segundos y consulta el estado. No reenvíes el comprobante.Ver detalle

Siguientes pasos

Empieza hoy

Obtén tu API key y prueba el ejemplo

Prueba la API en el ambiente de pruebas del SRI y pasa a producción cuando estés listo.