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

# Tokenization

> Securely store payment credentials using Waffo Tokens to enable one-click checkout, recurring billing, and delayed charges without handling raw card numbers.

export const CardGroup = ({children, cols = 2}) => {
  const items = Array.isArray(children) ? children.filter(Boolean) : [children];
  const layoutColumns = items.length === 3 ? 3 : cols === 1 ? 1 : 2;
  return <div className="waffo-guide-cards not-prose my-4 grid gap-4" data-columns={layoutColumns}>
      <style>{`
        .waffo-guide-cards {
          grid-template-columns: minmax(0, 1fr) !important;
        }
        .waffo-guide-cards .waffo-clickable-card {
          transition:
            transform 180ms ease,
            border-color 180ms ease,
            box-shadow 180ms ease,
            background 180ms ease !important;
        }
        html:not(.dark) .waffo-guide-cards .waffo-clickable-card:hover {
          border-color: rgba(109, 145, 245, 0.45) !important;
        }
        html.dark .waffo-guide-cards .waffo-clickable-card:hover,
        .dark .waffo-guide-cards .waffo-clickable-card:hover {
          border-color: rgba(109, 145, 245, 0.45) !important;
        }
        @media (min-width: 768px) {
          .waffo-guide-cards[data-columns="2"],
          .waffo-guide-cards[data-columns="3"] {
            grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
          }
          .waffo-guide-cards[data-columns="3"] .waffo-guide-card:nth-of-type(3) {
            grid-column: 1 / -1 !important;
          }
        }
      `}</style>
      {items}
    </div>;
};

export const Card = ({title, icon, href, children}) => {
  const resolvedHref = (() => {
    if (!href || typeof href !== "string") return href;
    if (!href.startsWith("/") || href.startsWith("//")) return href;
    if (typeof window === "undefined") return href;
    const docsPrefixMatch = window.location.pathname.match(/^\/docs(?=\/|$)/);
    const docsPrefix = docsPrefixMatch ? docsPrefixMatch[0] : "";
    if (!docsPrefix) {
      return href.startsWith("/docs/") ? href.slice(5) : href;
    }
    return href.startsWith(`${docsPrefix}/`) ? href : `${docsPrefix}${href}`;
  })();
  const Wrapper = resolvedHref ? "a" : "div";
  const interactiveClass = resolvedHref ? "waffo-clickable-card" : "";
  return <Wrapper href={resolvedHref} className={`waffo-guide-card waffo-hover-card block rounded-xl border border-slate-200 dark:border-neutral-700 bg-gradient-to-b from-slate-50 to-white dark:from-neutral-900 dark:to-neutral-950 p-6 no-underline ${interactiveClass}`}>
      <div className="flex flex-col items-start gap-3">
        <span className="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 text-blue-700 dark:text-[#4D7CFF]">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            {icon === "arrow-right" && <path d="M5 12h14M13 5l7 7-7 7" />}
            {icon === "bell" && <path d="M10 21h4M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9" />}
            {icon === "code" && <>
                <path d="m16 18 6-6-6-6" />
                <path d="m8 6-6 6 6 6" />
              </>}
            {icon === "globe" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="M2 12h20" />
                <path d="M12 2a15.3 15.3 0 0 1 0 20" />
                <path d="M12 2a15.3 15.3 0 0 0 0 20" />
              </>}
            {icon === "gear" && <>
                <circle cx="12" cy="12" r="3" />
                <path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.6-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.9.3H9a1.7 1.7 0 0 0 1-1.6V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9v.1a1.7 1.7 0 0 0 1.6 1h.1a2 2 0 1 1 0 4H21a1.7 1.7 0 0 0-1.6 1Z" />
              </>}
            {icon === "shield-check" && <>
                <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z" />
                <path d="m9 12 2 2 4-4" />
              </>}
            {icon === "circle-check" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="m9 12 2 2 4-4" />
              </>}
            {icon === "arrow-trend-up" && <path d="m3 17 6-6 4 4 8-8M14 7h7v7" />}
            {icon === "arrows-rotate" && <>
                <path d="M21 12a9 9 0 0 1-15.5 6.2" />
                <path d="M3 12A9 9 0 0 1 18.5 5.8" />
                <path d="M21 3v6h-6" />
                <path d="M3 21v-6h6" />
              </>}
            {icon === "calendar" && <>
                <rect x="3" y="4" width="18" height="17" rx="2" />
                <path d="M16 2v4M8 2v4M3 10h18" />
              </>}
            {icon === "clock" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="M12 6v6l4 2" />
              </>}
            {icon === "desktop" && <>
                <rect x="3" y="4" width="18" height="12" rx="2" />
                <path d="M8 20h8M12 16v4" />
              </>}
            {icon === "calculator" && <>
                <rect x="5" y="2" width="14" height="20" rx="2" />
                <path d="M8 6h8M8 10h.01M12 10h.01M16 10h.01M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01M16 18h.01" />
              </>}
            {icon === "plug" && <>
                <path d="M12 22v-5" />
                <path d="M9 8V2" />
                <path d="M15 8V2" />
                <path d="M18 8v5a6 6 0 0 1-12 0V8Z" />
              </>}
            {icon === "gauge" && <>
                <path d="M12 14l4-4" />
                <path d="M3.3 19a10 10 0 1 1 17.4 0" />
              </>}
            {icon === "layer-group" && <>
                <path d="m12 3 9 5-9 5-9-5 9-5Z" />
                <path d="m3 12 9 5 9-5" />
                <path d="m3 16 9 5 9-5" />
              </>}
            {icon === "laptop-mobile" && <>
                <rect x="3" y="4" width="13" height="10" rx="2" />
                <path d="M2 18h12" />
                <rect x="17" y="8" width="5" height="12" rx="1" />
              </>}
            {icon === "paintbrush" && <>
                <path d="m14 5 5 5" />
                <path d="M4 20c2 0 4-1 4-3 0-1.1-.9-2-2-2-2 0-3 2-3 4 0 .6.4 1 1 1Z" />
                <path d="m6 15 9-9a2.1 2.1 0 0 1 3 3l-9 9" />
              </>}
            {icon === "key" && <>
                <circle cx="7.5" cy="14.5" r="4.5" />
                <path d="m11 11 8-8" />
                <path d="m15 7 2 2" />
              </>}
            {icon === "circle-minus" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="M8 12h8" />
              </>}
            {icon === "wallet" && <>
                <path d="M3 7h15a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H3Z" />
                <path d="M3 7V5a2 2 0 0 1 2-2h11" />
                <path d="M16 14h.01" />
              </>}
            {icon === "users" && <>
                <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
                <circle cx="9" cy="7" r="4" />
                <path d="M22 21v-2a4 4 0 0 0-3-3.9" />
                <path d="M16 3.1a4 4 0 0 1 0 7.8" />
              </>}
            {icon === "link" && <>
                <path d="M10 13a5 5 0 0 0 7.1 0l2-2a5 5 0 0 0-7.1-7.1l-1.1 1.1" />
                <path d="M14 11a5 5 0 0 0-7.1 0l-2 2a5 5 0 0 0 7.1 7.1l1.1-1.1" />
              </>}
            {icon === "eye" && <>
                <path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z" />
                <circle cx="12" cy="12" r="3" />
              </>}
            {icon === "file-lines" && <>
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
                <path d="M14 2v6h6" />
                <path d="M8 13h8M8 17h6" />
              </>}
            {icon === "sliders" && <>
                <path d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3" />
                <path d="M2 14h4M10 8h4M18 16h4" />
              </>}
            {icon === "folder" && <path d="M3 6a2 2 0 0 1 2-2h5l2 2h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z" />}
            {icon === "dollar-sign" && <>
                <path d="M12 2v20" />
                <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7H14a3.5 3.5 0 0 1 0 7H6" />
              </>}
            {icon === "toggle-on" && <>
                <rect x="2" y="7" width="20" height="10" rx="5" />
                <circle cx="16" cy="12" r="3" />
              </>}
            {icon === "infinity" && <path d="M18.2 8.2c2.1 0 3.8 1.7 3.8 3.8s-1.7 3.8-3.8 3.8c-4.2 0-8.2-7.6-12.4-7.6C3.7 8.2 2 9.9 2 12s1.7 3.8 3.8 3.8c4.2 0 8.2-7.6 12.4-7.6Z" />}
            {icon === "book-open" && <>
                <path d="M2 4h7a3 3 0 0 1 3 3v14a3 3 0 0 0-3-3H2Z" />
                <path d="M22 4h-7a3 3 0 0 0-3 3v14a3 3 0 0 1 3-3h7Z" />
              </>}
            {icon === "circle-play" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="m10 8 6 4-6 4Z" />
              </>}
            {icon === "gamepad" && <>
                <rect x="3" y="8" width="18" height="10" rx="5" />
                <path d="M8 13h3M9.5 11.5v3M16 13h.01M18 11h.01" />
              </>}
            {icon === "rocket" && <>
                <path d="M4.5 16.5c-1.5 1.3-2 3.5-2 5 1.5 0 3.7-.5 5-2" />
                <path d="M9 15 4 10l6-6c4-4 9-2 10-1 1 1 3 6-1 10l-6 6-5-5Z" />
                <path d="M15 9h.01" />
              </>}
            {(icon === "flask" || icon === "flask-vial") && <>
                <path d="M9 2v6L4 20a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2L15 8V2" />
                <path d="M8 2h8" />
                <path d="M7 16h10" />
              </>}
            {icon === "credit-card" && <>
                <rect x="3" y="5" width="18" height="14" rx="2" />
                <path d="M3 10h18" />
                <path d="M7 15h4" />
              </>}
            {icon === "puzzle-piece" && <path d="M14 7V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v3H3a1 1 0 0 0-1 1v4a2 2 0 0 0 2 2h2v3a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-3h3a2 2 0 0 0 2-2V8a1 1 0 0 0-1-1Z" />}
            {(icon === "arrows-spin" || icon === "repeat") && <>
                <path d="M17 2l4 4-4 4" />
                <path d="M3 11V9a4 4 0 0 1 4-4h14" />
                <path d="M7 22l-4-4 4-4" />
                <path d="M21 13v2a4 4 0 0 1-4 4H3" />
              </>}
            {icon === "coins" && <>
                <ellipse cx="8" cy="7" rx="5" ry="3" />
                <path d="M3 7v6c0 1.7 2.2 3 5 3s5-1.3 5-3V7" />
                <path d="M13 10c2.8 0 5 1.3 5 3v4c0 1.7-2.2 3-5 3-1.2 0-2.3-.2-3.1-.7" />
              </>}
            {icon === "triangle-exclamation" && <>
                <path d="m21.7 18-8-14a2 2 0 0 0-3.4 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3Z" />
                <path d="M12 9v4M12 17h.01" />
              </>}
            {icon === "list" && <>
                <path d="M8 6h13M8 12h13M8 18h13" />
                <path d="M3 6h.01M3 12h.01M3 18h.01" />
              </>}
            {icon === "star" && <path d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.3L5.8 21 7 14.2 2 9.3l6.9-1Z" />}
            {(icon === "rotate" || icon === "arrow-rotate-left") && <>
                <path d="M3 12a9 9 0 1 0 3-6.7" />
                <path d="M3 4v6h6" />
              </>}
            {icon === "clock-rotate-left" && <>
                <path d="M3 12a9 9 0 1 0 3-6.7" />
                <path d="M3 4v6h6" />
                <path d="M12 7v5l3 2" />
              </>}
            {icon === "circle-xmark" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="m15 9-6 6M9 9l6 6" />
              </>}
            {icon === "paper-plane" && <path d="m22 2-7 20-4-9-9-4Z" />}
            {icon === "signal" && <>
                <path d="M2 20h.01M7 20v-4M12 20v-8M17 20V8M22 20V4" />
              </>}
            {icon === "circle-question" && <>
                <circle cx="12" cy="12" r="10" />
                <path d="M9.1 9a3 3 0 1 1 5.8 1c0 2-3 2-3 4" />
                <path d="M12 17h.01" />
              </>}
            {icon === "palette" && <>
                <path d="M12 22a10 10 0 1 1 7.5-3.4c-.9 1-2.4.4-2.4-.9 0-1.1-.9-2-2-2h-1.4c-1.2 0-2.2 1-2.2 2.2 0 1.1.9 2.1 2.1 2.1" />
                <circle cx="7.5" cy="10.5" r=".8" />
                <circle cx="12" cy="7.5" r=".8" />
                <circle cx="16.5" cy="10.5" r=".8" />
              </>}
            {(!icon || !["arrow-right", "bell", "code", "globe", "gear", "shield-check", "circle-check", "arrow-trend-up", "arrows-rotate", "calendar", "clock", "desktop", "calculator", "plug", "gauge", "layer-group", "laptop-mobile", "paintbrush", "key", "circle-minus", "wallet", "users", "link", "eye", "file-lines", "sliders", "folder", "dollar-sign", "toggle-on", "infinity", "book-open", "circle-play", "gamepad", "rocket", "flask", "flask-vial", "credit-card", "puzzle-piece", "arrows-spin", "repeat", "coins", "triangle-exclamation", "list", "star", "rotate", "arrow-rotate-left", "clock-rotate-left", "circle-xmark", "paper-plane", "signal", "circle-question", "palette"].includes(icon)) && <path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z" />}
          </svg>
        </span>
        <div className="flex flex-col gap-2">
          <h4 className="m-0 text-base font-semibold text-slate-900 dark:text-slate-100">
            {title}
          </h4>
          <div className="m-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
            {children}
          </div>
        </div>
      </div>
    </Wrapper>;
};

export const TokenizationUseCases = ({cases = []}) => {
  const icons = [<path key="bolt" d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z" />, <path key="rotate" d="M21 12a9 9 0 1 1-3-6.7M21 4v6h-6" />, <path key="clock" d="M12 8v5l3 2M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z" />];
  return <div className="not-prose my-5 grid grid-cols-1 gap-4 md:grid-cols-2">
      {cases.map((item, index) => <div key={item.title} className={`waffo-hover-card rounded-xl border border-slate-200 dark:border-neutral-700 bg-gradient-to-b from-slate-50 to-white dark:from-neutral-900 dark:to-neutral-950 p-5 ${index === 2 ? "md:col-span-2" : ""}`}>
          <div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 text-blue-700 dark:text-[#4D7CFF]">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              {icons[index] || icons[0]}
            </svg>
          </div>
          <h3 className="m-0 text-base font-semibold text-slate-900 dark:text-slate-100">
            {item.title}
          </h3>
          <p className="mt-3 mb-0 text-sm font-medium text-slate-700 dark:text-slate-200">
            {item.scenario}
          </p>
          <p className="mt-3 mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
            {item.description}
          </p>
        </div>)}
    </div>;
};

export const TokenizationCoreValueCards = ({items = []}) => {
  const iconSrc = "/images/essentials/tokenization/check-icon.svg";
  return <div className="tokenization-core-value-cards not-prose my-4 grid grid-cols-1 gap-4 md:grid-cols-2">
      <style>{`
        .tokenization-core-value-cards .tokenization-core-value-card {
          padding: 24px !important;
          box-sizing: border-box;
        }
        @media (min-width: 768px) {
          .tokenization-core-value-cards .tokenization-core-value-card:nth-of-type(3) {
            grid-column: 1 / -1 !important;
          }
        }
        .tokenization-core-value-cards .tokenization-check-icon {
          background-color: #071f66;
        }
        .dark .tokenization-core-value-cards .tokenization-check-icon {
          background-color: #4D7CFF;
        }
      `}</style>
      {items.map(item => <div key={item.title} className="tokenization-core-value-card waffo-hover-card rounded-xl border border-slate-200 dark:border-neutral-700 bg-gradient-to-b from-slate-50 to-white dark:from-neutral-900 dark:to-neutral-950">
          <div className="flex flex-col items-start gap-3">
            <span className="tokenization-check-icon inline-flex h-6 w-6 shrink-0" aria-hidden="true" style={{
    WebkitMask: `url("${iconSrc}") center / contain no-repeat`,
    mask: `url("${iconSrc}") center / contain no-repeat`
  }} />
            <div className="flex flex-col gap-2">
              <h4 className="m-0 text-base font-semibold text-slate-900 dark:text-slate-100">
                {item.title}
              </h4>
              <p className="m-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
                {item.description}
              </p>
            </div>
          </div>
        </div>)}
    </div>;
};

export const TokenizationIntegrationMigration = ({methods = [], migrationTitle, migrationDescription, migrationItems = [], apiLabel, apiHref = "/docs/api-reference/introduction"}) => {
  const methodIcons = ["object", "code"];
  return <div className="not-prose my-5 flex flex-col gap-4">
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        {methods.map((method, index) => <div key={method.title} className="waffo-hover-card relative overflow-hidden rounded-xl border border-slate-200 dark:border-neutral-700 bg-gradient-to-b from-slate-50 to-white dark:from-neutral-900 dark:to-neutral-950 p-5">
            <div className="absolute right-0 top-0 h-28 w-28 rounded-full bg-blue-100/70 dark:bg-blue-950/40 blur-2xl" />
            <div className="relative flex flex-col gap-4">
              <div className="flex items-center gap-3">
                <div className="flex h-10 w-10 items-center justify-center rounded-lg border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 text-blue-700 dark:text-[#4D7CFF]">
                  {methodIcons[index] === "code" ? <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <path d="m16 18 6-6-6-6" />
                      <path d="m8 6-6 6 6 6" />
                    </svg> : <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <rect x="3" y="3" width="7" height="7" rx="1.5" />
                      <rect x="14" y="3" width="7" height="7" rx="1.5" />
                      <rect x="3" y="14" width="7" height="7" rx="1.5" />
                      <path d="M14 17.5h7" />
                      <path d="M17.5 14v7" />
                    </svg>}
                </div>
                <h3 className="m-0 text-base font-semibold text-slate-900 dark:text-slate-100">
                  {method.title}
                </h3>
              </div>
              <p className="m-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
                {method.description}
              </p>
              {method.imageSrc && <div className="mt-1 overflow-hidden rounded-lg border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-900">
                  <img src={method.imageSrc} alt={method.imageAlt || method.title} className="m-0 block h-auto w-full" />
                </div>}
            </div>
          </div>)}
      </div>

      <div className="rounded-xl border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-950 overflow-hidden">
        <div className="border-b border-slate-200 dark:border-neutral-800 bg-slate-50 dark:bg-neutral-900 px-5 py-4">
          <h3 className="m-0 text-base font-semibold text-slate-900 dark:text-slate-100">
            {migrationTitle}
          </h3>
          <p className="mt-2 mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
            {migrationDescription}
          </p>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 divide-y md:divide-y-0 md:divide-x divide-slate-200 dark:divide-neutral-800">
          {migrationItems.map(item => <div key={item.title} className="p-5">
              <div className="mb-3 flex items-center gap-2">
                <span className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-50 dark:bg-blue-950/60 text-blue-700 dark:text-[#4D7CFF]">
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                    <path d={item.type === "export" ? "M12 3v13" : "M12 21V8"} />
                    <path d={item.type === "export" ? "m7 8 5-5 5 5" : "m7 16 5 5 5-5"} />
                    <path d="M5 21h14" />
                  </svg>
                </span>
                <h4 className="m-0 text-sm font-semibold text-slate-900 dark:text-slate-100">
                  {item.title}
                </h4>
              </div>
              <p className="m-0 text-sm leading-6 text-slate-600 dark:text-slate-300">
                {item.description}
              </p>
            </div>)}
        </div>
      </div>

      <a href={apiHref} className="inline-flex self-start items-center gap-2 rounded-lg border border-slate-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 px-4 py-2 text-sm font-medium text-blue-700 dark:text-[#4D7CFF] no-underline hover:bg-slate-50 dark:hover:bg-neutral-800">
        {apiLabel}
        <span aria-hidden="true">→</span>
      </a>
    </div>;
};

Tokenization technology enables merchants to store user payment information securely without handling raw card numbers. It replaces sensitive bank card data with a non-sensitive random string — the **Waffo Token**.

Waffo provides a standardized Tokenization solution. Merchants integrate with a unified Token interface to achieve **"One-Click Payment"** and **"Recurring Billing"** without managing complex card scheme rules or security encryption details.

## Core value

<TokenizationCoreValueCards
  items={[
{
  title: "Ultimate payment experience",
  description:
    "Users only need to enter their card details once. Subsequent purchases require no re-entry, drastically reducing checkout friction.",
},
{
  title: "Reduced compliance costs",
  description:
    "Sensitive data is hosted in Waffo's PCI-DSS Level 1 certified vault. Merchant systems never process plaintext card numbers, significantly reducing the scope of compliance audits.",
},
{
  title: "Cross-channel universality",
  description:
    "Generated Tokens can be used across all your channels — App, Web, Mobile Web, and more — to build a unified user payment account system.",
},
]}
/>

## Why choose Waffo Tokenization

Our Token is not just a simple storage credential. It integrates Waffo's Smart Payment Engine to continuously optimize your transaction performance.

### Smart optimization

Waffo employs multiple industry-leading optimization technologies at the infrastructure level. When you initiate a charge using a Waffo Token, the intelligent engine automatically selects the optimal ISO message format and routing strategy based on issuing bank preferences, transaction types, and risk characteristics.

<CardGroup cols={2}>
  <Card title="Effect" icon="arrow-trend-up">
    Transactions initiated via Waffo Token achieve higher authorization approval rates compared to traditional raw card payments.
  </Card>

  <Card title="Seamless" icon="circle-check">
    All optimizations occur automatically within milliseconds, requiring no extra configuration from you.
  </Card>
</CardGroup>

### Account updater

Waffo is deeply integrated with major card scheme networks to support automated card lifecycle management.

<CardGroup cols={2}>
  <Card title="Auto-renewal" icon="arrows-rotate">
    When a user's physical card expires, is reported lost or replaced, or the card number changes, the system automatically retrieves the latest card information.
  </Card>

  <Card title="Zero business interruption" icon="infinity">
    Waffo silently updates the mapping relationship in the background. Your **Waffo Token string remains unchanged**, but it now points to the new card — ensuring subscription charges don't fail due to card replacement.
  </Card>
</CardGroup>

## Use cases

<TokenizationUseCases
  cases={[
{
title: "One-click checkout",
scenario: "Scenario: A returning user shopping again at the merchant.",
description: 'The user sees "Pay with Visa ending in 8888" directly on the checkout page. They click a button to complete the order without taking out their wallet or entering card details again.'
},
{
title: "Recurring & subscription",
scenario: "Scenario: Monthly SaaS software payments, video membership renewals.",
description: "Establish a recurring billing schedule via Token. The merchant initiates MIT (Merchant Initiated Transaction) instructions periodically to achieve silent deduction."
},
{
title: "Booking & delayed charge",
scenario: "Scenario: Hotel bookings, deposit for shared services.",
description: "The user authorizes the Token at booking, optionally combined with pre-authorization to freeze funds. The merchant initiates the charge via Token based on the actual consumption amount."
}
]}
/>

## Lifecycle management flow

<Steps>
  <Step title="Create Token">
    * **User side:** The user checks "Save this card for future use" at checkout.
    * **System side:** Waffo validates card data, performs multi-layer encryption, and returns a Token ID to the merchant.
  </Step>

  <Step title="Verify & charge">
    * **Verify:** Perform a Zero-Auth (0 amount) or \$1 pre-authorization at the time of binding to confirm the card is active and chargeable.
    * **Charge:** When initiating a payment, your backend sends the Token ID directly — no card number required.
  </Step>

  <Step title="Manage & display">
    * Retrieve a list of all bound Tokens for a specific user via API.
    * The API returns masked information (Card Brand, Last 4 Digits, Expiry Date, Card Art Background Color) for frontend display and user selection.
  </Step>
</Steps>

## Integration & migration

### Integration methods

<TokenizationIntegrationMigration
  methods={[
{
  title: "UI component integration",
  description: "Use Waffo Elements. The component automatically handles card number collection and tokenization internally, so your frontend code never touches plaintext card numbers.",
  imageSrc: "/images/essentials/tokenization/UI%20Component%20Integration.png?v=20260429-1822",
  imageAlt: "UI component integration flow"
},
{
  title: "API integration",
  description: "Suitable for PCI-certified merchants, allowing direct Token creation via server-side API while keeping sensitive data within a compliant environment.",
  imageSrc: "/images/essentials/tokenization/API%20Integration.png?v=20260429-1822",
  imageAlt: "API integration flow"
}
]}
  migrationTitle="Data migration"
  migrationDescription="Waffo supports flexible data migration schemes to eliminate vendor lock-in concerns."
  migrationItems={[
{
  type: "import",
  title: "Import",
  description: "Smoothly migrate existing Token data from other platforms to Waffo. Returning users do not need to re-bind cards."
},
{
  type: "export",
  title: "Export",
  description: "If you stop using the service, Waffo securely transmits encrypted card data to a qualified recipient in accordance with PCI standards."
}
]}
  apiLabel="View API Documentation"
  apiHref="/api-reference/introduction"
/>

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Is saving credit cards secure?">
    Extremely secure. Waffo holds the highest level of security certification, PCI-DSS Level 1 (Financial Grade Security Standard). Actual card number data is encrypted and stored in physically isolated vaults. The merchant's system and database store only the meaningless Token string. Even if the merchant's database is compromised, hackers cannot reconstruct the real bank card information.
  </Accordion>

  <Accordion title="Does the Token expire?">
    The Waffo Token itself is permanently valid unless you proactively call the API to delete it. Even if the underlying physical card expires, thanks to our Account Updater feature, the system automatically maintains the mapping relationship in most cases without manual intervention from you or the user.
  </Accordion>

  <Accordion title="How do I verify that the bound card is valid?">
    We recommend performing a Zero Amount Verify at the same time the Token is created. This ensures that the card corresponding to the Token is real, valid, not reported lost, and capable of being charged at the moment of binding.
  </Accordion>

  <Accordion title="Can I share the Token with my sub-merchants?">
    This depends on your account architecture. If you are a Platform merchant, you can authorize payment credentials to sub-merchants via "Token Cloning" to achieve a unified wallet experience.
  </Accordion>
</AccordionGroup>

***

Need help? [Contact support](mailto:support@waffo.com)
