> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gifty.lat/llms.txt
> Use this file to discover all available pages before exploring further.

# El ciclo de una gift card

> Una referencia para distinguir producto, pedido, emisión, entrega y canje.

export const GiftJourney = ({locale = "es-AR", fallback, fallbackHref}) => {
  const L = locale === "en" ? "en" : locale === "pt-BR" ? "pt" : "es";
  const T = {
    es: {
      t: "El recorrido de un regalo",
      step: "Paso",
      of: "de",
      prev: "Paso anterior",
      next: "Paso siguiente",
      play: "Reproducir",
      pause: "Pausar",
      rule: "Regla clave",
      q: "En cola",
      d: "Entregado",
      on: "Online",
      ct: "Mostrador",
      fb: "Leé estas reglas en texto",
      s: [["Producto", "El producto define la oferta", "Montos, vigencia, textos y diseño definen la oferta. El producto se usa para vender o emitir regalos.", "Un producto todavía no es un regalo: nadie tiene saldo hasta la emisión."], ["Pedido", "Un pedido puede tener varias unidades", "Cada unidad se configura por separado: para quién es, con qué mensaje y cuándo se envía. Tres unidades son tres futuros regalos.", "Cada unidad pendiente necesita su configuración; otras unidades del pedido pueden estar emitidas."], ["Emisión", "La emisión crea cada regalo y su saldo", "Al emitirse, cada unidad se convierte en un regalo con código y saldo propios. Confirmar el pedido no demuestra que todas sus unidades estén emitidas.", "Reemitir es una emisión nueva. No reenvía nada."], ["Entrega", "La entrega envía ESE regalo", "El canal disponible lleva un regalo puntual al destinatario. En cola no demuestra entrega: revisá el resultado final en la cronología.", "Si la entrega falla, reintentala para el mismo regalo. Reemitir NO es reintentar la entrega."], ["Canje", "El canje consume el saldo", "La persona usa el saldo del regalo comprando online o en el mostrador de tu local.", "Revisá importe y comprobante. Si queda un intento pendiente, resolvelo desde la misma operación."]]
    },
    en: {
      t: "The journey of a gift",
      step: "Step",
      of: "of",
      prev: "Previous step",
      next: "Next step",
      play: "Play",
      pause: "Pause",
      rule: "Key rule",
      q: "Queued",
      d: "Delivered",
      on: "Online",
      ct: "Counter",
      fb: "Read these rules as text",
      s: [["Product", "The product defines the offer", "Amounts, validity, copy and design define the offer. The product is used to sell or issue gifts.", "A product is not a gift yet: nobody holds a balance until issuance."], ["Order", "An order can hold several units", "Each unit is configured on its own: who it is for, the message, and when it is sent. Three units are three future gifts.", "Each pending unit needs configuration; other units in the order may already be issued."], ["Issuance", "Issuance creates each gift and its balance", "At issuance, each unit becomes a gift with its own code and balance. Order confirmation does not prove every unit is issued.", "Reissuing is a new issuance. It does not resend anything."], ["Delivery", "Delivery sends THAT gift", "The available channel carries one specific gift to its recipient. Queued is not proof of delivery: check the final timeline result.", "If a delivery fails, retry it for the same gift. Reissuing is NOT retrying delivery."], ["Redemption", "Redemption consumes the balance", "The recipient spends the gift balance by buying online or at your store counter.", "Check amount and receipt. If an attempt remains pending, resolve it from the same operation."]]
    },
    pt: {
      t: "A jornada de um presente",
      step: "Etapa",
      of: "de",
      prev: "Etapa anterior",
      next: "Próxima etapa",
      play: "Reproduzir",
      pause: "Pausar",
      rule: "Regra-chave",
      q: "Na fila",
      d: "Entregue",
      on: "Online",
      ct: "Balcão",
      fb: "Leia estas regras em texto",
      s: [["Produto", "O produto define a oferta", "Valores, validade, textos e design definem a oferta. O produto é usado para vender ou emitir presentes.", "Um produto ainda não é um presente: ninguém tem saldo até a emissão."], ["Pedido", "Um pedido pode ter várias unidades", "Cada unidade é configurada separadamente: para quem é, com qual mensagem e quando será enviada. Três unidades são três futuros presentes.", "Cada unidade pendente precisa de configuração; outras unidades do pedido podem já estar emitidas."], ["Emissão", "A emissão cria cada presente e seu saldo", "Na emissão, cada unidade vira um presente com código e saldo próprios. Confirmar o pedido não comprova emissão de todas as unidades.", "Reemitir é uma nova emissão. Não reenvia nada."], ["Entrega", "A entrega envia AQUELE presente", "O canal disponível leva um presente específico ao destinatário. Na fila não comprova entrega: confira o resultado final na linha do tempo.", "Se a entrega falhar, tente de novo para o mesmo presente. Reemitir NÃO é reenviar."], ["Resgate", "O resgate consome o saldo", "A pessoa usa o saldo do presente comprando online ou no balcão da sua loja.", "Confira valor e comprovante. Se uma tentativa ficar pendente, resolva na mesma operação."]]
    }
  };
  const c = T[L];
  const [i, setI] = useState(0);
  const [playing, setPlaying] = useState(false);
  const [rm, setRm] = useState(false);
  useEffect(() => {
    const m = window.matchMedia("(prefers-reduced-motion: reduce)");
    const sync = () => {
      setRm(m.matches);
      if (m.matches) setPlaying(false);
    };
    sync();
    m.addEventListener("change", sync);
    return () => m.removeEventListener("change", sync);
  }, []);
  useEffect(() => {
    if (!playing || rm) return;
    const id = setInterval(() => setI(s => {
      if (s >= 4) {
        setPlaying(false);
        return 4;
      }
      return s + 1;
    }), 5000);
    return () => clearInterval(id);
  }, [playing, rm]);
  const s = c.s[i];
  const icons = ["M3 3h8l9 9-8 8-9-9zM7 7h.01", "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z", "M4 8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v2a2 2 0 0 0 0 4v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-4z", "M4 12l16-8-6 16-2-6z", "M5 12l5 5 9-11"];
  const tk = "M0 8a8 8 0 0 1 8-8h40a8 8 0 0 1 8 8v20a6 6 0 0 0 0 12v20a8 8 0 0 1-8 8H8a8 8 0 0 1-8-8V48a6 6 0 0 0 0-12z";
  const scenes = [<g><rect x="50" y="24" width="140" height="112" rx="12" className="gj-card" /><path d="M70 44h30l22 22-22 22H70z" className="gj-acc-s" /><circle cx="80" cy="54" r="3" className="gj-acc-f" /><rect x="132" y="48" width="40" height="8" rx="4" className="gj-bar" /><rect x="132" y="66" width="28" height="8" rx="4" className="gj-bar" /><rect x="70" y="100" width="100" height="8" rx="4" className="gj-bar" /><rect x="70" y="116" width="64" height="8" rx="4" className="gj-bar" /></g>, <g>{[0, 1, 2].map(k => <g key={k} transform={`translate(${28 + k * 64} 40)`}><rect width="56" height="80" rx="10" className="gj-card" /><circle cx="28" cy="24" r="10" className={k === 1 ? "gj-acc-f" : "gj-bar"} /><rect x="12" y="44" width="32" height="6" rx="3" className="gj-bar" /><rect x="12" y="58" width={[22, 30, 18][k]} height="6" rx="3" className="gj-bar" /></g>)}</g>, <g>{[0, 1, 2].map(k => <g key={k} transform={`translate(${28 + k * 64} 48)`}><path d={tk} className="gj-card" /><rect x="10" y="14" width="36" height="6" rx="3" className="gj-bar" /><rect x="10" y="42" width="36" height="8" rx="4" className="gj-acc-f" /></g>)}</g>, <g><g transform="translate(24 52)"><path d={tk} className="gj-card gj-acc-s" /><rect x="10" y="42" width="36" height="8" rx="4" className="gj-acc-f" /></g><path d="M92 80h44m-8-8l8 8-8 8" className="gj-line" /><g transform="translate(148 36)"><circle cx="20" cy="20" r="16" className="gj-ring" /><path d="M20 10v10l6 4" className="gj-line" /><text x="44" y="24" className="gj-t">{c.q}</text></g><g transform="translate(148 88)"><circle cx="20" cy="20" r="16" className="gj-acc-f" /><path d="M12 20l6 6 10-12" className="gj-line-inv" /><text x="44" y="24" className="gj-t">{c.d}</text></g></g>, <g><g transform="translate(24 52)"><path d={tk} className="gj-card" /><rect x="10" y="42" width="36" height="8" rx="4" className="gj-bar" /><rect x="10" y="42" width="16" height="8" rx="4" className="gj-acc-f" /></g><path d="M92 80h36" className="gj-line" /><g transform="translate(140 36)"><circle cx="20" cy="20" r="14" className="gj-ring" /><path d="M6 20h28M20 6c-8 8-8 20 0 28M20 6c8 8 8 20 0 28" className="gj-line" /><text x="44" y="24" className="gj-t">{c.on}</text></g><g transform="translate(140 88)"><path d="M6 16l4-10h20l4 10v18H6z" className="gj-ring" /><path d="M6 16h28M14 34V24h12v10" className="gj-line" /><text x="44" y="24" className="gj-t">{c.ct}</text></g></g>];
  return <section className="gj" aria-label={c.t}>
      <div className="gj-head">
        <div><h3 className="gj-title">{c.t}</h3><p className="gj-count">{c.step} {i + 1} {c.of} 5</p></div>
        <div className="gj-ctl">
          <button type="button" className="gj-btn" aria-label={c.prev} onClick={() => {
    setPlaying(false);
    setI(Math.max(0, i - 1));
  }} disabled={i === 0}><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6" /></svg></button>
          <button type="button" className="gj-btn" aria-label={c.next} onClick={() => {
    setPlaying(false);
    setI(Math.min(4, i + 1));
  }} disabled={i === 4}><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6" /></svg></button>
          {!rm && <button type="button" className="gj-btn gj-play" aria-pressed={playing} onClick={() => {
    if (i === 4) setI(0);
    setPlaying(!playing);
  }}>{playing ? c.pause : c.play}</button>}
        </div>
      </div>
      <ol className="gj-rail">
        {c.s.map((x, k) => <li key={k}><button type="button" className={"gj-step" + (k === i ? " is-on" : k < i ? " is-done" : "")} aria-current={k === i ? "step" : undefined} onClick={() => {
    setI(k);
    setPlaying(false);
  }}>
            <span className="gj-badge"><svg viewBox="0 0 24 24" aria-hidden="true"><path d={icons[k]} /></svg></span><span>{k + 1}. {x[0]}</span>
          </button></li>)}
      </ol>
      <div className="gj-panel" key={i}>
        <svg className="gj-scene" viewBox="0 0 300 160" role="img" aria-label={s[1]}>{scenes[i]}</svg>
        <div><h4 className="gj-h">{s[1]}</h4><p className="gj-p">{s[2]}</p><p className="gj-rule"><strong>{c.rule}</strong> {s[3]}</p></div>
      </div>
      <p className="gifty-visually-hidden" aria-live="polite">{c.step} {i + 1} {c.of} 5: {s[1]}</p>
      <p className="gj-fb">{fallbackHref ? <a href={fallbackHref}>{fallback || c.fb}</a> : fallback || c.fb}</p>
    </section>;
};

<GiftJourney locale="es-AR" fallback="Leé la explicación completa en texto." fallbackHref="#del-producto-al-canje" />

Una gift card pasa por procesos diferentes. Separarlos permite detectar dónde hace falta actuar y evita confundir un pago, un envío o un canje con otro evento.

## Del producto al canje

| Etapa                 | Qué representa                                         | Qué no prueba por sí sola                                    |
| --------------------- | ------------------------------------------------------ | ------------------------------------------------------------ |
| Producto de gift card | La opción que se publica en el catálogo de la tienda.  | Que alguien la haya comprado.                                |
| Pedido pagado         | La compra que debe procesarse.                         | Que todas las unidades estén configuradas y entregadas.      |
| Configuración         | Los datos necesarios para cada regalo y destinatario.  | Que la emisión haya finalizado.                              |
| Emisión               | La creación de la gift card de una unidad.             | Que el destinatario haya recibido el mensaje.                |
| Entrega               | Los intentos y resultados del envío de esa gift card.  | Que el destinatario la haya abierto o canjeado.              |
| Regalo público        | La página que abre el destinatario mediante su enlace. | Una nueva compra o un canje completado.                      |
| Canje                 | El uso de valor y la actualización de su saldo.        | Que toda la gift card se haya agotado si el uso fue parcial. |

Una emisión manual empieza desde la acción del comercio, sin exigir un pedido del checkout. La documentación distingue esa puerta de entrada de la compra online.

## Integraciones actuales y límites

Tiendanube es la plataforma de ecommerce de este recorrido. Marketing Nube tiene una superficie propia de conexión y audiencias; su alcance debe consultarse en esa integración. Ninguna de estas conexiones significa que exista una API pública transaccional de gifty.

## API pública: no disponible

**La API pública transaccional no está disponible.** No hay un endpoint público documentado en esta documentación para emitir, consultar saldos o canjear. No invoques `POST /gift-cards` ni deduzcas un contrato a partir de rutas internas de la app.

Una futura referencia API deberá definir autenticación, permisos, idempotencia, errores, límites y versionado sobre una implementación aprobada. Esta página no anuncia fecha ni contrato de esa API.

## Información para agentes

Las páginas públicas sirven para explicar el producto y citar sus reglas. No autorizan acceso a datos de una tienda. El saldo de un código concreto requiere una lectura autenticada y permitida; no se infiere de esta documentación.

El Markdown de estas páginas se genera desde el mismo contenido editorial. Los SVG tienen equivalentes de texto. Los índices de conocimiento son documentales: no son herramientas para ejecutar operaciones en gifty.

## Si necesitás ayuda con un caso

Identificá la etapa, la referencia de la operación y el resultado observado. El soporte humano se atiende por el canal de WhatsApp de gifty; esta documentación no inicia una conversación ni confirma recepción de un caso. Un click en un enlace no equivale a un mensaje recibido.

[Guía de emisión y entrega](/es/issue-and-deliver) · [Concepto de saldo](/es/balance)

[Leer esta página en Markdown](/exports/es/gift-lifecycle.md)
