> ## 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.

# The gift card lifecycle

> A reference for products, orders, issuance, delivery and redemption.

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="en" fallback="Read the complete explanation as text." fallbackHref="#from-product-to-redemption" />

A gift card moves through different processes. Distinguishing them helps you find where action is needed and avoids mistaking a payment, a message or a redemption for another event.

## From product to redemption

| Stage             | What it represents                               | What it does not prove on its own                      |
| ----------------- | ------------------------------------------------ | ------------------------------------------------------ |
| Gift card product | The option published in the store catalog.       | That someone has bought it.                            |
| Paid order        | The purchase that needs processing.              | That every unit is configured and delivered.           |
| Configuration     | The details needed for each gift and recipient.  | That issuance has finished.                            |
| Issuance          | Creating the gift card for a unit.               | That the recipient received the message.               |
| Delivery          | Attempts and outcomes of sending that gift card. | That the recipient opened or redeemed it.              |
| Public gift       | The page the recipient opens through their link. | A new purchase or completed redemption.                |
| Redemption        | Using value and updating its balance.            | That the whole card is exhausted when use was partial. |

Manual issuance starts from a merchant action without requiring a checkout order. Documentation distinguishes that entry point from an online purchase.

## Current integrations and limits

Tiendanube is the ecommerce platform for this flow. Marketing Nube has its own connection and audiences surface; consult that integration for its scope. Neither connection implies a public transactional gifty API exists.

## Public API: not available

**The public transactional API is not available.** This pilot documents no public endpoint for issuing gift cards, checking balances or redeeming. Do not invoke `POST /gift-cards` or infer a contract from internal app routes.

A future API reference must define authentication, permissions, idempotency, errors, limits and versioning against an approved implementation. This page announces neither an API date nor a contract.

## Information for agents

Public pages explain the product and support citations of its rules. They do not authorize access to store data. The balance of a specific code requires an authenticated, permitted read; it cannot be inferred from these docs.

Markdown is generated from the same editorial content. SVGs have text equivalents. Knowledge indexes provide documentation, not tools to execute operations in gifty.

## If you need help with a case

Identify the stage, operation reference and observed outcome. Human support uses gifty's WhatsApp channel; this documentation does not start a conversation or confirm receipt of a case. Clicking a link is not the same as a received message.

[Issuance and delivery guide](/en/issue-and-deliver) · [Balance concept](/en/balance)

[Read this page as Markdown](/exports/en/gift-lifecycle.md)
