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

# Quick Start

> Choose your integration path and process your first in-person payment

export const WizardInit = () => {
  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }
    var STEP_IDS = ['step1-type', 'step1-standalone', 'step2-path', 'step3-providers', 'step3-h2h-content', 'step3-c2c-fork', 'step3-c2c-api-content', 'step3-c2c-sdk-content'];
    window._wizardPath = window._wizardPath || 'h2h';
    function getCheckedProviderCount() {
      return document.querySelectorAll('#step3-providers input[type="checkbox"]:checked').length;
    }
    function updateProviderContinueState() {
      var continueButton = document.getElementById('provider-continue-button');
      var helperText = document.getElementById('provider-continue-hint');
      if (!continueButton || !helperText) return;
      var hasSelection = getCheckedProviderCount() > 0;
      continueButton.disabled = !hasSelection;
      continueButton.setAttribute('aria-disabled', hasSelection ? 'false' : 'true');
      helperText.style.display = hasSelection ? 'none' : 'block';
    }
    function applyPathPresentation(path) {
      var effectivePath = path === 'c2c' ? 'c2c' : 'h2h';
      window._wizardPath = effectivePath;
      var atomSection = document.getElementById('provider-atom-section');
      var atomCheckbox = document.getElementById('atom-checkbox');
      var atomCard = document.getElementById('provider-atom');
      var h2hBanner = document.getElementById('path-banner-h2h');
      var c2cBanner = document.getElementById('path-banner-c2c');
      if (effectivePath === 'c2c') {
        if (atomSection) atomSection.style.display = 'none';
        if (atomCheckbox) atomCheckbox.checked = false;
        if (atomCard) atomCard.classList.remove('selected');
        if (h2hBanner) h2hBanner.style.display = 'none';
        if (c2cBanner) c2cBanner.style.display = 'flex';
      } else {
        if (atomSection) atomSection.style.display = '';
        if (h2hBanner) h2hBanner.style.display = 'flex';
        if (c2cBanner) c2cBanner.style.display = 'none';
      }
    }
    function setVisibleStep(stepId) {
      STEP_IDS.forEach(function (id) {
        var section = document.getElementById(id);
        if (!section) return;
        section.style.display = id === stepId ? 'block' : 'none';
      });
    }
    function resolvePathFromStep(stepId) {
      if (stepId.indexOf('c2c') >= 0) return 'c2c';
      if (stepId.indexOf('h2h') >= 0) return 'h2h';
      return window._wizardPath || 'h2h';
    }
    function restoreFromHash() {
      var rawHash = (window.location.hash || '').replace('#', '');
      var stepId = STEP_IDS.indexOf(rawHash) >= 0 ? rawHash : 'step1-type';
      var resolvedPath = resolvePathFromStep(stepId);
      applyPathPresentation(resolvedPath);
      setVisibleStep(stepId);
      updateProviderContinueState();
    }
    window._updateProviderContinueState = updateProviderContinueState;
    window._toggleProvider = function (id) {
      var cb = document.getElementById(id + '-checkbox');
      var card = document.getElementById('provider-' + id);
      if (!cb || !card) return;
      cb.checked = !cb.checked;
      card.classList.toggle('selected', cb.checked);
      updateProviderContinueState();
      if (window.updateC2CProviderSnippets) window.updateC2CProviderSnippets();
      if (window.updateH2HProviderSnippets) window.updateH2HProviderSnippets();
    };
    window.addEventListener('hashchange', restoreFromHash);
    restoreFromHash();
    return () => {
      window.removeEventListener('hashchange', restoreFromHash);
      if (window._updateProviderContinueState === updateProviderContinueState) {
        delete window._updateProviderContinueState;
      }
      delete window._toggleProvider;
    };
  }, []);
  return null;
};

export const H2HProviderSnippetInit = () => {
  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }
    const PROVIDER_CONFIG = {
      bri: {
        key: 'bri',
        androidCall: 'TerminalBRI',
        iosCall: 'TerminalBRI.shared',
        androidDependency: 'implementation("co.xendit.terminal:id-bri-android:<latest_version>")',
        iosDependency: 'Add TerminalBRI.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/h2h/ios-sdk#installation.'
      },
      cashup: {
        key: 'cashup',
        androidCall: 'TerminalCashup',
        iosCall: 'TerminalCashup.shared',
        androidDependency: 'implementation("co.xendit.terminal:id-cashup-android:<latest_version>")',
        iosDependency: 'Add TerminalCashup.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/h2h/ios-sdk#installation. Contact Xendit for access.'
      },
      ntt: {
        key: 'ntt',
        androidCall: 'TerminalNTT',
        iosCall: 'TerminalNTT.shared',
        androidDependency: 'implementation("co.xendit.terminal:th-ntt-android:<latest_version>")',
        iosDependency: 'Add TerminalNTT.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/h2h/ios-sdk#installation. Contact Xendit for access.'
      },
      shc: {
        key: 'shc',
        androidCall: 'TerminalSHC',
        iosCall: 'TerminalSHC.shared',
        androidDependency: 'implementation("co.xendit.terminal:my-shc-android:<latest_version>")',
        iosDependency: 'Add TerminalSHC.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/h2h/ios-sdk#installation. Contact Xendit for access.'
      }
    };
    const SUPPORTED_KEYS = Object.keys(PROVIDER_CONFIG);
    function buildAndroidProviderLines(selectedKeys) {
      const lines = selectedKeys.map(key => `    TerminalH2H.addProvider(${PROVIDER_CONFIG[key].androidCall})`);
      return lines.length ? lines.join('\n') : '    TerminalH2H.addProvider(TerminalBRI)';
    }
    function buildIosProviderLines(selectedKeys) {
      const lines = selectedKeys.map(key => `  TerminalH2H.shared.addProvider(provider: ${PROVIDER_CONFIG[key].iosCall})`);
      return lines.length ? lines.join('\n') : '  TerminalH2H.shared.addProvider(provider: TerminalBRI.shared)';
    }
    function buildAndroidDependencyLines(selectedKeys) {
      const providerKeys = selectedKeys.length ? selectedKeys : ['bri'];
      return ['  // Terminal H2H SDK', '  implementation("co.xendit.terminal:h2h-android:<latest_version>")', '', '  // Core Terminal SDK (required)', '  implementation("co.xendit.terminal:core-android:<latest_version>")', '', ...providerKeys.map(key => `  ${PROVIDER_CONFIG[key].androidDependency}`)].join('\n');
    }
    function buildIosDependencyLines(selectedKeys) {
      if (!selectedKeys.length) {
        return '- Add TerminalBRI.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/h2h/ios-sdk#installation.';
      }
      return selectedKeys.map(key => `- ${PROVIDER_CONFIG[key].iosDependency}`).join('\n');
    }
    function highlight(codeElement) {
      if (typeof window === 'undefined' || !codeElement) {
        return;
      }
      if (window.Prism?.highlightElement) {
        window.Prism.highlightElement(codeElement);
      }
    }
    function getSelectedProviderKeys() {
      return SUPPORTED_KEYS.filter(key => {
        const checkbox = document.getElementById(`${key}-checkbox`);
        return checkbox ? checkbox.checked : false;
      });
    }
    const updateSnippets = () => {
      const androidProviderCode = document.querySelector('#h2h-android-provider-snippet pre code, #h2h-android-provider-snippet code');
      const iosProviderCode = document.querySelector('#h2h-ios-provider-snippet pre code, #h2h-ios-provider-snippet code');
      const androidDependencyCode = document.querySelector('#h2h-android-dependency-snippet pre code, #h2h-android-dependency-snippet code');
      const iosDependencyCode = document.querySelector('#h2h-ios-dependency-snippet pre code, #h2h-ios-dependency-snippet code');
      if (!androidProviderCode || !iosProviderCode || !androidDependencyCode || !iosDependencyCode) {
        window.setTimeout(updateSnippets, 100);
        return;
      }
      const providerKeys = getSelectedProviderKeys();
      const effectiveKeys = providerKeys.length ? providerKeys : ['bri'];
      androidProviderCode.textContent = `import co.xendit.terminal.core.TerminalApp
import co.xendit.terminal.h2h.TerminalH2H

class App : Application() {
  override fun onCreate() {
    super.onCreate()

    TerminalApp.initialize(
      context = this,
      clientKey = CLIENT_KEY,
      mode = TerminalMode.LIVE // or TerminalMode.INTEGRATION
    )
${buildAndroidProviderLines(effectiveKeys)}
  }
}`;
      iosProviderCode.textContent = `import TerminalH2H
import TerminalCore

func application(
  _ application: UIApplication,
  didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
  TerminalApp.shared.initialize(
    clientKey: CLIENT_KEY,
    mode: TerminalMode.live // or TerminalMode.integration
  )
${buildIosProviderLines(effectiveKeys)}
  return true
}`;
      androidDependencyCode.textContent = `dependencies {
${buildAndroidDependencyLines(effectiveKeys)}
}`;
      iosDependencyCode.textContent = `# Add these provider frameworks using Xcode (General > Frameworks, Libraries, and Embedded Content).
# See /sdk/h2h/ios-sdk#installation for installation steps.

${buildIosDependencyLines(effectiveKeys)}`;
      highlight(androidProviderCode);
      highlight(iosProviderCode);
      highlight(androidDependencyCode);
      highlight(iosDependencyCode);
    };
    const handler = () => {
      updateSnippets();
      window.setTimeout(updateSnippets, 250);
    };
    window.updateH2HProviderSnippets = handler;
    handler();
    return () => {
      if (window.updateH2HProviderSnippets === handler) {
        delete window.updateH2HProviderSnippets;
      }
    };
  }, []);
  return null;
};

export const C2CProviderSnippetInit = () => {
  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }
    const PROVIDER_CONFIG = {
      bri: {
        key: 'bri',
        androidCall: 'TerminalBRI',
        iosCall: 'TerminalBRI.shared',
        deviceValue: 'BRI',
        androidDependency: 'implementation("co.xendit.terminal:id-bri-android:<latest_version>")',
        iosDependency: 'Add TerminalBRI.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation.'
      },
      cashup: {
        key: 'cashup',
        androidCall: 'TerminalCashup',
        iosCall: 'TerminalCashup.shared',
        deviceValue: 'CASHUP',
        androidDependency: 'implementation("co.xendit.terminal:id-cashup-android:<latest_version>")',
        iosDependency: 'Add TerminalCashup.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation. Contact Xendit for access.'
      },
      ntt: {
        key: 'ntt',
        androidCall: 'TerminalNTT',
        iosCall: 'TerminalNTT.shared',
        deviceValue: 'NTT',
        androidDependency: 'implementation("co.xendit.terminal:th-ntt-android:<latest_version>")',
        iosDependency: 'Add TerminalNTT.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation. Contact Xendit for access.'
      },
      shc: {
        key: 'shc',
        androidCall: 'TerminalSHC',
        iosCall: 'TerminalSHC.shared',
        deviceValue: 'SHC',
        androidDependency: 'implementation("co.xendit.terminal:my-shc-android:<latest_version>")',
        iosDependency: 'Add TerminalSHC.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation. Contact Xendit for access.'
      }
    };
    const SUPPORTED_KEYS = Object.keys(PROVIDER_CONFIG);
    function buildAndroidProviderLines(selectedKeys) {
      return selectedKeys.map(key => `    TerminalC2C.addProvider(${PROVIDER_CONFIG[key].androidCall})`).join('\n') || '    TerminalC2C.addProvider(TerminalBRI)';
    }
    function buildIosProviderLines(selectedKeys) {
      return selectedKeys.map(key => `  TerminalC2C.shared.addProvider(provider: ${PROVIDER_CONFIG[key].iosCall})`).join('\n') || '  TerminalC2C.shared.addProvider(provider: TerminalBRI.shared)';
    }
    function buildDeviceLines(selectedKeys) {
      if (!selectedKeys.length) {
        return {
          android: '  provider = "BRI"',
          ios: '  provider: "BRI"'
        };
      }
      if (selectedKeys.length === 1) {
        const value = PROVIDER_CONFIG[selectedKeys[0]].deviceValue;
        return {
          android: `  provider = "${value}"`,
          ios: `  provider: "${value}"`
        };
      }
      const primary = PROVIDER_CONFIG[selectedKeys[0]].deviceValue;
      const others = selectedKeys.slice(1).map(key => PROVIDER_CONFIG[key].deviceValue).join(', ');
      return {
        android: `  provider = "${primary}" // or ${others}`,
        ios: `  provider: "${primary}" // or ${others}`
      };
    }
    function buildAndroidDependencyLines(selectedKeys) {
      const providerKeys = selectedKeys.length ? selectedKeys : ['bri'];
      return ['  // Terminal C2C SDK', '  implementation("co.xendit.terminal:c2c-android:<latest_version>")', '', '  // Core Terminal SDK (required)', '  implementation("co.xendit.terminal:core-android:<latest_version>")', '', ...providerKeys.map(key => `  ${PROVIDER_CONFIG[key].androidDependency}`)].join('\n');
    }
    function buildIosDependencyLines(selectedKeys) {
      return selectedKeys.map(key => `- ${PROVIDER_CONFIG[key].iosDependency}`).join('\n') || '- Add TerminalBRI.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation.';
    }
    function highlight(codeElement) {
      if (typeof window === 'undefined' || !codeElement) {
        return;
      }
      if (window.Prism?.highlightElement) {
        window.Prism.highlightElement(codeElement);
      }
    }
    function getSelectedProviderKeys() {
      return SUPPORTED_KEYS.filter(key => {
        const checkbox = document.getElementById(`${key}-checkbox`);
        return checkbox ? checkbox.checked : false;
      });
    }
    function ensureElements(...elements) {
      return elements.every(Boolean);
    }
    const updateSnippets = () => {
      const androidProviderCode = document.querySelector('#c2c-android-provider-snippet pre code, #c2c-android-provider-snippet code');
      const iosProviderCode = document.querySelector('#c2c-ios-provider-snippet pre code, #c2c-ios-provider-snippet code');
      const androidDeviceCode = document.querySelector('#c2c-android-device-snippet pre code, #c2c-android-device-snippet code');
      const iosDeviceCode = document.querySelector('#c2c-ios-device-snippet pre code, #c2c-ios-device-snippet code');
      const androidDependencyCode = document.querySelector('#c2c-android-dependency-snippet pre code, #c2c-android-dependency-snippet code');
      const iosDependencyCode = document.querySelector('#c2c-ios-dependency-snippet pre code, #c2c-ios-dependency-snippet code');
      if (!ensureElements(androidProviderCode, iosProviderCode, androidDeviceCode, iosDeviceCode, androidDependencyCode, iosDependencyCode)) {
        window.setTimeout(updateSnippets, 100);
        return;
      }
      const providerKeys = getSelectedProviderKeys();
      const effectiveKeys = providerKeys.length ? providerKeys : ['bri'];
      const deviceLines = buildDeviceLines(effectiveKeys);
      androidProviderCode.textContent = `import co.xendit.terminal.c2c.TerminalC2C
import co.xendit.terminal.core.TerminalApp

class App : Application() {
  override fun onCreate() {
    super.onCreate()

    TerminalApp.initialize(
      context = this,
      clientKey = CLIENT_KEY,
      mode = TerminalMode.LIVE // or TerminalMode.INTEGRATION
    )
${buildAndroidProviderLines(effectiveKeys)}
  }
}`;
      iosProviderCode.textContent = `import TerminalC2C
import TerminalCore

func application(
  _ application: UIApplication,
  didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
  TerminalApp.shared.initialize(
    clientKey: CLIENT_KEY,
    mode: TerminalMode.live // or TerminalMode.integration
  )
${buildIosProviderLines(effectiveKeys)}
  return true
}`;
      androidDeviceCode.textContent = `val terminalDevice = TerminalDevice.create(
  id = "TID001",
  ipAddress = "192.168.1.100",
${deviceLines.android}
)

TerminalC2C.setTerminalDevice(terminalDevice)`;
      iosDeviceCode.textContent = `let terminalDevice = TerminalDevice.companion.create(
  id: "TID001",
  ipAddress: "192.168.1.100",
${deviceLines.ios}
)

TerminalC2C.shared.setTerminalDevice(terminalDevice)`;
      androidDependencyCode.textContent = `dependencies {
${buildAndroidDependencyLines(effectiveKeys)}
}`;
      iosDependencyCode.textContent = `# Add these provider frameworks to your target
${buildIosDependencyLines(effectiveKeys)}`;
      highlight(androidProviderCode);
      highlight(iosProviderCode);
      highlight(androidDeviceCode);
      highlight(iosDeviceCode);
      highlight(androidDependencyCode);
      highlight(iosDependencyCode);
    };
    const handler = () => {
      updateSnippets();
      window.setTimeout(updateSnippets, 250);
    };
    window.updateC2CProviderSnippets = handler;
    handler();
    return () => {
      if (window.updateC2CProviderSnippets === handler) {
        delete window.updateC2CProviderSnippets;
      }
    };
  }, []);
  return null;
};

<WizardInit />

<C2CProviderSnippetInit />

<H2HProviderSnippetInit />

<div id="step1-type">
  <div className="wizard-step-indicator">
    <div className="wizard-step active">
      <span className="wizard-step-dot">1</span>
      <span>Integration type</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step">
      <span className="wizard-step-dot">2</span>
      <span>Integration path</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step">
      <span className="wizard-step-dot">3</span>
      <span>Get started</span>
    </div>
  </div>

  <div style={{ marginBottom: '8px' }}>
    <h2 style={{ fontWeight: '700', marginBottom: '8px', fontSize: '24px' }}>
      Choose how you want to accept payments
    </h2>

    <p style={{ maxWidth: '560px', margin: '0', color: 'var(--terminal-text-secondary)', fontSize: '15px' }}>
      Pick the fastest route for your business now. You can switch to a deeper integration path later.
    </p>
  </div>

  <div className="quickstart-choice-grid">
    <div
      className="quickstart-card"
      style={{ padding: '24px' }}
      onClick={() => {
    document.getElementById('step1-type').style.display = 'none';
    document.getElementById('step1-standalone').style.display = 'block';
    window.location.hash = 'step1-standalone';
  }}
    >
      <div style={{ fontSize: '28px', marginBottom: '12px' }}>📱</div>
      <div style={{ fontWeight: '700', fontSize: '17px', marginBottom: '6px' }}>Device-Only Setup</div>

      <div style={{ color: 'var(--terminal-text-secondary)', fontSize: '14px', lineHeight: '1.5' }}>
        Enter amounts manually on the device. No API or SDK integration needed.
      </div>
    </div>

    <div
      className="quickstart-card"
      style={{ padding: '24px' }}
      onClick={() => {
    document.getElementById('step1-type').style.display = 'none';
    document.getElementById('step2-path').style.display = 'block';
    window.location.hash = 'step2-path';
  }}
    >
      <div style={{ fontSize: '28px', marginBottom: '12px' }}>🔗</div>
      <div style={{ fontWeight: '700', fontSize: '17px', marginBottom: '6px' }}>POS-Integrated</div>

      <div style={{ color: 'var(--terminal-text-secondary)', fontSize: '14px', lineHeight: '1.5' }}>
        Connect your POS, kiosk, or custom software to the terminal via API or SDK.
      </div>
    </div>
  </div>
</div>

<div id="step1-standalone" className="quickstart-content" style={{display: 'none'}}>
  <button
    className="quickstart-back-button"
    onClick={() => {
  document.getElementById('step1-standalone').style.display = 'none';
  document.getElementById('step1-type').style.display = 'block';
  window.location.hash = '';
}}
    style={{ marginBottom: '20px' }}
  >
    <svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20">
      <path fillRule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0L3.586 10l4.707-4.707a1 1 0 011.414 1.414L6.414 10l3.293 3.293a1 1 0 010 1.414z" clipRule="evenodd" />
    </svg>

    Back
  </button>

  <h2 style={{ fontWeight: '700', marginBottom: '12px', fontSize: '24px' }}>Device-Only Setup</h2>

  <p style={{ maxWidth: '600px', color: 'var(--terminal-text-secondary)', fontSize: '15px', lineHeight: '1.6' }}>
    For merchants without a POS integration, payments can be accepted directly on the terminal by manually entering amounts. No API or SDK setup is required. Transactions are visible in your Xendit Dashboard.
  </p>

  <div style={{ marginTop: '20px' }}>
    <a href="/guides/getting-started/standalone-terminal" className="quickstart-link-card">
      <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
        <div>📖</div>

        <div>
          <div style={{ fontWeight: '600', marginBottom: '4px' }}>Device-Only Setup Guide</div>
          <div>Learn how to use the terminal without any integration</div>
        </div>
      </div>
    </a>
  </div>
</div>

<div id="step2-path" className="quickstart-content" style={{display: 'none'}}>
  <div className="wizard-step-indicator">
    <div className="wizard-step completed">
      <span className="wizard-step-dot">
        <svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>
      </span>

      <span>Integration type</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step active">
      <span className="wizard-step-dot">2</span>
      <span>Integration path</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step">
      <span className="wizard-step-dot">3</span>
      <span>Get started</span>
    </div>
  </div>

  <div style={{ marginBottom: '32px' }}>
    <button
      className="quickstart-back-button"
      onClick={() => {
    document.getElementById('step2-path').style.display = 'none';
    document.getElementById('step1-type').style.display = 'block';
    window.location.hash = '';
  }}
      style={{ marginBottom: '20px' }}
    >
      <svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20">
        <path fillRule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0L3.586 10l4.707-4.707a1 1 0 011.414 1.414L6.414 10l3.293 3.293a1 1 0 010 1.414z" clipRule="evenodd" />
      </svg>

      Back
    </button>

    <h2 style={{ fontWeight: '700', marginBottom: '8px', fontSize: '24px' }}>
      Choose your integration path
    </h2>

    <p style={{ maxWidth: '560px', margin: '0', color: 'var(--terminal-text-secondary)', fontSize: '15px' }}>
      Select the integration approach that best fits your technical requirements.
    </p>
  </div>

  <div className="quickstart-elevated">
    <table className="quickstart-table">
      <thead>
        <tr>
          <th className="quickstart-table-heading green" style={{ width: '50%' }}>
            <div style={{ fontWeight: '700', marginBottom: '4px' }}>Host-to-Host (H2H) — Terminal API</div>
            <div>Recommended for most merchants</div>
          </th>

          <th className="quickstart-table-heading neutral" style={{ width: '50%' }}>
            <div style={{ fontWeight: '700', marginBottom: '4px' }}>Client-to-Client (C2C)</div>
            <div>Terminal C2C API or Terminal C2C SDK</div>
          </th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td className="quickstart-table-cell green">
            Your backend calls Xendit's cloud HTTP API. Managed orchestration with minimal custom code.
          </td>

          <td className="quickstart-table-cell">
            Your POS talks to terminals over the local network via HTTP REST commands or native SDK methods.
          </td>
        </tr>

        <tr>
          <td className="quickstart-table-cell green">
            Uses Terminal API sessions for payments, callbacks, and reconciliation.
          </td>

          <td className="quickstart-table-cell">
            Sends PAY / CANCEL / SETTLEMENT commands directly — via Terminal C2C API (HTTP) or Terminal C2C SDK (native).
          </td>
        </tr>

        <tr>
          <td className="quickstart-table-cell green">
            Xendit manages device orchestration and infrastructure.
          </td>

          <td className="quickstart-table-cell">
            Your team owns device connectivity, error handling, and security.
          </td>
        </tr>
      </tbody>
    </table>

    <div className="wizard-button-grid">
      <button
        className="wizard-button-primary green"
        onClick={() => {
    window._wizardPath = 'h2h';
    document.getElementById('step2-path').style.display = 'none';

    const atomSection = document.getElementById('provider-atom-section');
    if (atomSection) atomSection.style.display = '';
    const h2hBanner = document.getElementById('path-banner-h2h');
    const c2cBanner = document.getElementById('path-banner-c2c');
    if (h2hBanner) h2hBanner.style.display = 'flex';
    if (c2cBanner) c2cBanner.style.display = 'none';
    if (window._updateProviderContinueState) window._updateProviderContinueState();

    document.getElementById('step3-providers').style.display = 'block';
    window.location.hash = 'step3-providers';
  }}
      >
        <svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>

        Continue with H2H
      </button>

      <button
        className="wizard-button-secondary"
        onClick={() => {
    window._wizardPath = 'c2c';
    document.getElementById('step2-path').style.display = 'none';

    const atomSection = document.getElementById('provider-atom-section');
    const atomCb = document.getElementById('atom-checkbox');
    const atomCard = document.getElementById('provider-atom');
    if (atomSection) atomSection.style.display = 'none';
    if (atomCb) atomCb.checked = false;
    if (atomCard) atomCard.classList.remove('selected');
    const h2hBanner = document.getElementById('path-banner-h2h');
    const c2cBanner = document.getElementById('path-banner-c2c');
    if (h2hBanner) h2hBanner.style.display = 'none';
    if (c2cBanner) c2cBanner.style.display = 'flex';
    if (window._updateProviderContinueState) window._updateProviderContinueState();

    document.getElementById('step3-providers').style.display = 'block';
    window.location.hash = 'step3-providers';
  }}
      >
        <svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
        </svg>

        Continue with C2C
      </button>
    </div>

    <Info>
      **Not sure?** H2H fits most deployments for its simplicity and speed. Explore the [Terminal API (H2H) docs](/api-reference/terminal-api/introduction) or [C2C docs](/api-reference/c2c/introduction) for deeper details.
    </Info>
  </div>
</div>

<div id="step3-providers" className="quickstart-content" style={{display: 'none'}}>
  <div className="wizard-step-indicator">
    <div className="wizard-step completed">
      <span className="wizard-step-dot">
        <svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>
      </span>

      <span>Integration type</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step completed">
      <span className="wizard-step-dot">
        <svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>
      </span>

      <span>Integration path</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step active">
      <span className="wizard-step-dot">3</span>
      <span>Get started</span>
    </div>
  </div>

  <div style={{ marginBottom: '24px' }}>
    <button
      className="quickstart-back-button"
      onClick={() => {
    document.getElementById('step3-providers').style.display = 'none';
    document.getElementById('step2-path').style.display = 'block';
    window.location.hash = 'step2-path';
  }}
    >
      <svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20">
        <path fillRule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0L3.586 10l4.707-4.707a1 1 0 011.414 1.414L6.414 10l3.293 3.293a1 1 0 010 1.414z" clipRule="evenodd" />
      </svg>

      Back to integration path
    </button>
  </div>

  {/* Path banners — JS toggles the matching one */}

  <div id="path-banner-h2h" className="selection-banner h2h-banner" style={{display: 'none'}}>
    <svg style={{ width: '24px', height: '24px' }} fill="currentColor" viewBox="0 0 20 20">
      <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
    </svg>

    <div>
      <h3 style={{ margin: '0', fontWeight: '600' }}>Host-to-Host (H2H) — Terminal API</h3>
      <p style={{ margin: '0', opacity: '0.8' }}>Your backend calls Xendit's cloud API via HTTP</p>
    </div>
  </div>

  <div id="path-banner-c2c" className="selection-banner c2c-banner" style={{display: 'none'}}>
    <svg style={{ width: '24px', height: '24px' }} fill="currentColor" viewBox="0 0 20 20">
      <path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
    </svg>

    <div>
      <h3 style={{ margin: '0', fontWeight: '600' }}>Client-to-Client (C2C)</h3>
      <p style={{ margin: '0', opacity: '0.8' }}>Your POS communicates directly with terminals over the local network</p>
    </div>
  </div>

  <div style={{ marginBottom: '8px' }}>
    <h3 style={{ fontWeight: '700', marginBottom: '8px', fontSize: '20px' }}>
      Select your payment provider(s)
    </h3>

    <p style={{ maxWidth: '520px', margin: '0', color: 'var(--terminal-text-secondary)', fontSize: '15px' }}>
      Choose the terminal providers you plan to integrate. You can select more than one.
    </p>
  </div>

  <div className="quickstart-provider-container">
    {/* Indonesia */}

    <div className="country-section">
      <h3 className="country-header"><span className="country-flag">🇮🇩</span> Indonesia</h3>

      <div className="provider-grid">
        <div id="provider-bri" className="provider-card quickstart-card" onClick={() => { window._toggleProvider('bri'); }}>
          <div className="provider-icon">
            <img src="https://mintcdn.com/xendit/iTqGX9_7zwXBWkal/images/providers/bri.png?fit=max&auto=format&n=iTqGX9_7zwXBWkal&q=85&s=5c192b86596beb81a1bccf9dcab3dd5b" alt="BRI" width="1564" height="592" data-path="images/providers/bri.png" />
          </div>

          <div className="provider-info">
            <div className="provider-name">BRI</div>
            <div className="provider-desc">Bank Rakyat Indonesia terminals</div>
          </div>

          <input type="checkbox" id="bri-checkbox" />
        </div>

        <div id="provider-cashup" className="provider-card quickstart-card" onClick={() => { window._toggleProvider('cashup'); }}>
          <div className="provider-icon">
            <img src="https://mintcdn.com/xendit/iTqGX9_7zwXBWkal/images/providers/cashup.png?fit=max&auto=format&n=iTqGX9_7zwXBWkal&q=85&s=b26f71a73db823a7e36b20c893654981" alt="Cashup" width="2565" height="2565" data-path="images/providers/cashup.png" />
          </div>

          <div className="provider-info">
            <div className="provider-name">
              Cashup
            </div>

            <div className="provider-desc">Multi-brand payment terminals</div>
          </div>

          <input type="checkbox" id="cashup-checkbox" />
        </div>
      </div>
    </div>

    {/* Thailand */}

    <div className="country-section">
      <h3 className="country-header"><span className="country-flag">🇹🇭</span> Thailand</h3>

      <div className="provider-grid">
        <div id="provider-ntt" className="provider-card quickstart-card" onClick={() => { window._toggleProvider('ntt'); }}>
          <div className="provider-icon">
            <img src="https://mintcdn.com/xendit/N10u_CDYGVZ66cVf/images/providers/ntt-data.svg?fit=max&auto=format&n=N10u_CDYGVZ66cVf&q=85&s=6fd2be79ea3b9eac65a0d66ac1dbcbbf" alt="NTT DATA" width="400" height="101" data-path="images/providers/ntt-data.svg" />
          </div>

          <div className="provider-info">
            <div className="provider-name">NTT</div>
            <div className="provider-desc">NTT DATA payment terminals</div>
          </div>

          <input type="checkbox" id="ntt-checkbox" />
        </div>
      </div>
    </div>

    {/* Malaysia */}

    <div className="country-section">
      <h3 className="country-header"><span className="country-flag">🇲🇾</span> Malaysia</h3>

      <div className="provider-grid">
        <div id="provider-shc" className="provider-card quickstart-card" onClick={() => { window._toggleProvider('shc'); }}>
          <div className="provider-icon">
            <img src="https://mintcdn.com/xendit/iTqGX9_7zwXBWkal/images/providers/share-commerce.webp?fit=max&auto=format&n=iTqGX9_7zwXBWkal&q=85&s=91b57e408b7df4f104305eb449ff05c0" alt="Share Commerce" width="400" height="92" data-path="images/providers/share-commerce.webp" />
          </div>

          <div className="provider-info">
            <div className="provider-name">Share Commerce</div>
            <div className="provider-desc">Retail payment terminals</div>
          </div>

          <input type="checkbox" id="shc-checkbox" />
        </div>
      </div>
    </div>

    {/* Vietnam — hidden for C2C (Atom is H2H-only) */}

    <div id="provider-atom-section" className="country-section">
      <h3 className="country-header"><span className="country-flag">🇻🇳</span> Vietnam</h3>

      <div className="provider-grid">
        <div id="provider-atom" className="provider-card quickstart-card" onClick={() => { window._toggleProvider('atom'); }}>
          <div className="provider-icon">
            <img src="https://mintcdn.com/xendit/N10u_CDYGVZ66cVf/images/providers/atom.svg?fit=max&auto=format&n=N10u_CDYGVZ66cVf&q=85&s=15013a391e1282337fb09ab5c526d0bf" alt="Atom" width="117" height="46" data-path="images/providers/atom.svg" />
          </div>

          <div className="provider-info">
            <div className="provider-name">Atom</div>
            <div className="provider-desc">Payment terminals for Vietnam</div>
          </div>

          <input type="checkbox" id="atom-checkbox" />
        </div>
      </div>
    </div>
  </div>

  {/* Continue */}

  <div style={{ marginTop: '36px' }}>
    <button
      id="provider-continue-button"
      className="wizard-button-primary"
      onClick={() => {
    const hasSelectedProvider = document.querySelectorAll('#step3-providers input[type="checkbox"]:checked').length > 0;
    if (!hasSelectedProvider) {
      if (window._updateProviderContinueState) window._updateProviderContinueState();
      return;
    }

    const path = window._wizardPath;
    if (window.updateC2CProviderSnippets) window.updateC2CProviderSnippets();
    if (window.updateH2HProviderSnippets) window.updateH2HProviderSnippets();

    document.getElementById('step3-providers').style.display = 'none';

    if (path === 'h2h') {
      document.getElementById('step3-h2h-content').style.display = 'block';
      window.location.hash = 'step3-h2h-content';
    } else {
      document.getElementById('step3-c2c-fork').style.display = 'block';
      window.location.hash = 'step3-c2c-fork';
    }
  }}
    >
      <svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor">
        <path fillRule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clipRule="evenodd" />
      </svg>

      Continue with selected provider(s)
    </button>

    <p id="provider-continue-hint" className="wizard-helper-text" style={{ display: 'none' }}>
      Select at least one provider to continue.
    </p>
  </div>
</div>

<div id="step3-h2h-content" className="quickstart-content" style={{display: 'none'}}>
  ## Prerequisites

  * Terminal API key from the Xendit In-Person Payment team
  * Node.js or your preferred development environment

  ### For Physical Terminal Testing

  * Physical terminal device connected and showing "Ready" status
  * Terminal registered with Xendit for test mode (contact support if needed)
  * Valid `terminal_id` from your registered device

  ### For Simulation Testing (No Terminal Required)

  * Any `terminal_id` value (e.g., `SIM001`) — no registration needed
  * Special test amounts to trigger different payment scenarios
  * Use `4040404` as terminal\_id to test invalid terminal error handling

  <Info>
    **Don't have a physical terminal yet?** No problem! You can start integration immediately using simulation. Use special test amounts and terminal IDs to simulate different payment scenarios without physical hardware.
  </Info>

  <Warning>
    Use sandbox/test devices and small amounts while testing. Do not use production keys in development.
  </Warning>

  ## 1. Configure your environment

  Set up your local development environment with the necessary credentials and base URLs.

  <Steps>
    <Step title="Create environment file">
      Create a `.env` file in your project root:

      ```bash .env theme={null}
      TERMINAL_API_KEY=your_dev_terminal_api_key
      TERMINAL_BASE_URL=https://terminal-dev.xendit.co
      CALLBACK_URL=http://localhost:3000/terminal/callbacks
      TERMINAL_ID=TERM001
      ```

      <Warning>
        Never commit secrets to version control. Add `.env` to your `.gitignore` file.
      </Warning>
    </Step>

    <Step title="Install dependencies">
      Install required packages for your development environment:

      <CodeGroup>
        ```bash Node.js theme={null}
        npm install node-fetch express dotenv
        ```

        ```bash Python theme={null}
        pip install requests flask python-dotenv
        ```
      </CodeGroup>
    </Step>

    <Step title="Set up webhook server">
      Create a local Express server to receive callbacks:

      ```javascript webhook.js theme={null}
      import express from 'express';
      import dotenv from 'dotenv';

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

      app.post('/terminal/callbacks', (req, res) => {
      console.log('Event:', req.body?.event, req.body?.data?.status);
      console.log('Full payload:', JSON.stringify(req.body, null, 2));
      res.sendStatus(200);
      });

      app.listen(3000, () => {
        console.log('Webhook server running on http://localhost:3000');
        console.log('Use ngrok to expose this server for testing');
      });
      ```

      <Tip>
        Use ngrok (`npm install -g ngrok && ngrok http 3000`) to expose your local server publicly for webhook testing.
      </Tip>
    </Step>
  </Steps>

  ## 2. Choose your testing approach

  <Tabs>
    <Tab title="Simulation Testing (Recommended for getting started)">
      **Perfect for merchants waiting on terminal delivery or initial integration**

      Test payment flows without physical hardware using special test amounts and scenarios.

      <Steps>
        <Step title="Use any terminal ID">
          For simulation testing, you can use any `terminal_id` value. The system will automatically simulate payment responses.

          ```bash .env theme={null}
          TERMINAL_ID=SIM001  # Any value works for simulation
          ```
        </Step>

        <Step title="Test different scenarios">
          Use these special amounts to simulate various payment outcomes:

          | Amount                      | Scenario            | Expected Result                    |
          | --------------------------- | ------------------- | ---------------------------------- |
          | `400508`                    | Payment declined    | Session created, transaction fails |
          | `400509`                    | Channel unavailable | Session creation fails             |
          | `400711`                    | User cancellation   | Session created, then canceled     |
          | `4040404` (as terminal\_id) | Invalid terminal    | Session creation fails             |
          | Any other amount            | Success flow        | Payment completes successfully     |

          <Tip>
            Start with a normal amount like `10000` to test the success flow, then try the special amounts to test error handling.
          </Tip>
        </Step>

        <Step title="Run simulation test">
          ```javascript test-simulation.js theme={null}
          import fetch from 'node-fetch';
          import dotenv from 'dotenv';

          dotenv.config();

          async function testSimulation() {
            const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
            
            // Test successful payment simulation
            const successTest = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/sessions`, {
              method: 'POST',
              headers: {
                'Authorization': auth,
                'Content-Type': 'application/json',
                'Idempotency-key': `sim-success-${Date.now()}`,
              },
              body: JSON.stringify({
                session_type: 'PAY',
                mode: 'TERMINAL',
                currency: 'IDR',
                amount: 10000, // Normal amount = success
                country: 'ID',
                channel_properties: { terminal_id: 'SIM001' },
              }),
            });
            
            const successData = await successTest.json();
            console.log('✅ Success simulation:', successData.status);
            
            // Test payment decline simulation
            const declineTest = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/sessions`, {
              method: 'POST',
              headers: {
                'Authorization': auth,
                'Content-Type': 'application/json',
                'Idempotency-key': `sim-decline-${Date.now()}`,
              },
              body: JSON.stringify({
                session_type: 'PAY',
                mode: 'TERMINAL',
                currency: 'IDR',
                amount: 400508, // Special amount = decline
                country: 'ID',
                channel_properties: { terminal_id: 'SIM001' },
              }),
            });
            
            const declineData = await declineTest.json();
            console.log('⚠️ Decline simulation:', declineData.status);
          }

          testSimulation();
          ```

          <Check>
            You receive different responses based on the test amounts, simulating real payment scenarios without physical hardware.
          </Check>
        </Step>
      </Steps>

      <Note>
        **Simulation Benefits**: Start integration immediately, test error handling, validate webhook flows, and prepare for production - all without waiting for terminal delivery.
      </Note>
    </Tab>

    <Tab title="Physical Terminal Testing">
      **For merchants with connected terminal devices**

      Test with actual hardware for the most realistic payment experience.

      <Steps>
        <Step title="Verify terminal registration">
          Ensure your terminal is registered for test mode:

          * Check that your Terminal H2H shows "Connected" or "Ready" status
          * Confirm terminal is registered with Xendit (contact support if unsure)
          * Verify you're using test mode in Terminal H2H settings

          <Warning>
            Unregistered terminals will automatically fall back to simulation mode, even if physically connected.
          </Warning>
        </Step>

        <Step title="Test API connectivity">
          Make a test request to validate your API key and terminal setup:

          ```javascript test-terminal.js theme={null}
          import fetch from 'node-fetch';
          import dotenv from 'dotenv';

          dotenv.config();

          async function testTerminal() {
            const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
            
            const res = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/sessions`, {
              method: 'POST',
              headers: {
                'Authorization': auth,
                'Content-Type': 'application/json',
                'Idempotency-key': `test-${Date.now()}`,
              },
              body: JSON.stringify({
                session_type: 'PAY',
                mode: 'TERMINAL',
                currency: 'IDR',
                amount: 1000, // Small test amount
                country: 'ID',
                channel_properties: { terminal_id: process.env.TERMINAL_ID },
              }),
            });
            
            const data = await res.json();
            
            if (res.ok) {
              console.log('✅ Terminal connection successful');
              console.log('Session ID:', data.payment_session_id);
              console.log('Status:', data.status);
            } else {
              console.log('❌ Error:', data.error_code, data.message);
            }
          }

          testTerminal();
          ```

          <Check>
            You receive a 200 response with a session ID and the physical terminal prompts for payment.
          </Check>

          <Tip>
            If you get a `TERMINAL_NOT_FOUND` error, your terminal may not be registered. Contact Xendit support to register it for test mode.
          </Tip>
        </Step>

        <Step title="Validate physical interaction">
          Confirm the terminal responds to the API call:

          * Terminal display shows payment amount
          * Card reader is active and ready
          * Payment can be completed with test card
          * Webhook callbacks are received

          <Check>
            Physical terminal displays payment prompt and accepts card interactions.
          </Check>
        </Step>
      </Steps>
    </Tab>
  </Tabs>

  ## 3. Create your first payment session

  Now create a payment session and process it. Choose the approach that matches your setup:

  <Tabs>
    <Tab title="Simulation Payment">
      **Perfect for testing without physical terminals**

      <CodeGroup>
        ```bash cURL (Success Simulation) theme={null}
        curl -X POST 'https://terminal-dev.xendit.co/v1/terminal/sessions' \
          -u 'YOUR_TERMINAL_API_KEY:' \
          -H 'Content-Type: application/json' \
          -H 'Idempotency-key: sim-success-'"$(date +%s)" \
          -d '{
            "session_type": "PAY",
            "mode": "TERMINAL",
            "currency": "IDR",
            "amount": 10000,
            "country": "ID",
            "channel_properties": { "terminal_id": "SIM001" }
          }'
        ```

        ```bash cURL (Decline Simulation) theme={null}
        curl -X POST 'https://terminal-dev.xendit.co/v1/terminal/sessions' \
          -u 'YOUR_TERMINAL_API_KEY:' \
          -H 'Content-Type: application/json' \
          -H 'Idempotency-key: sim-decline-'"$(date +%s)" \
          -d '{
            "session_type": "PAY",
            "mode": "TERMINAL",
            "currency": "IDR",
            "amount": 400508,
            "country": "ID",
            "channel_properties": { "terminal_id": "SIM001" }
          }'
        ```

        ```javascript JavaScript (Simulation) theme={null}
        import fetch from 'node-fetch';
        import dotenv from 'dotenv';

        dotenv.config();

        async function createSimulationPayment(amount = 10000) {
          const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
          
          const res = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/sessions`, {
            method: 'POST',
            headers: {
              'Authorization': auth,
              'Content-Type': 'application/json',
              'Idempotency-key': `sim-payment-${Date.now()}`,
            },
            body: JSON.stringify({
              session_type: 'PAY',
              mode: 'TERMINAL',
              currency: 'IDR',
              amount: amount, // Use special amounts for different scenarios
              country: 'ID',
              channel_properties: { terminal_id: 'SIM001' },
            }),
          });
          
          const data = await res.json();
          console.log('Simulation payment session created:', data.payment_session_id);
          return data;
        }

        // Test different scenarios
        createSimulationPayment(10000);  // Success
        createSimulationPayment(400508); // Decline
        createSimulationPayment(400509); // Channel unavailable
        ```
      </CodeGroup>

      <Check>
        **Success**: Session created with `ACTIVE` status, then automatically transitions to `COMPLETED`\
        **Decline**: Session created with `ACTIVE` status, then transitions to `FAILED`
      </Check>
    </Tab>

    <Tab title="Physical Terminal Payment">
      **For merchants with connected terminals**

      <CodeGroup>
        ```bash cURL theme={null}
        curl -X POST 'https://terminal-dev.xendit.co/v1/terminal/sessions' \
          -u 'YOUR_TERMINAL_API_KEY:' \
          -H 'Content-Type: application/json' \
          -H 'Idempotency-key: payment-'"$(date +%s)" \
          -d '{
            "session_type": "PAY",
            "mode": "TERMINAL",
            "currency": "IDR",
            "amount": 10000,
            "country": "ID",
            "channel_properties": { "terminal_id": "TERM001" }
          }'
        ```

        ```javascript JavaScript theme={null}
        import fetch from 'node-fetch';
        import dotenv from 'dotenv';

        dotenv.config();

        async function createTerminalPayment(amount, terminalId) {
          const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
          
          const res = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/sessions`, {
            method: 'POST',
            headers: {
              'Authorization': auth,
              'Content-Type': 'application/json',
              'Idempotency-key': `payment-${Date.now()}`,
            },
            body: JSON.stringify({
              session_type: 'PAY',
              mode: 'TERMINAL',
              currency: 'IDR',
              amount: amount,
              country: 'ID',
              channel_properties: { terminal_id: terminalId },
            }),
          });
          
          const data = await res.json();
          console.log('Payment session created:', data.payment_session_id);
          return data;
        }

        // Use your registered terminal ID
        createTerminalPayment(10000, process.env.TERMINAL_ID);
        ```
      </CodeGroup>

      <Check>
        The terminal device prompts for payment. Ask the customer to tap/insert/swipe their card.
      </Check>

      <Tip>
        If the device doesn't prompt, verify the terminal is connected in Gateway and the `terminal_id` matches your device configuration.
      </Tip>
    </Tab>
  </Tabs>

  ## 4. Monitor callbacks

  Your webhook server (started in step 1) will receive real-time payment updates. Monitor the console output to see callback events.

  <Info>
    Callback events include `terminal_session.completed`, `terminal_session.canceled`, `terminal_payment.succeeded`, and others. See the [Callbacks documentation](/api-reference/terminal-api/callbacks) for complete event types.
  </Info>

  ## 5. Verify payment details

  Query payment details after receiving a success callback.

  <CodeGroup>
    ```bash cURL theme={null}
    curl -X GET 'https://terminal-dev.xendit.co/v1/terminal/payments/PAYMENT_ID' \
      -u 'YOUR_TERMINAL_API_KEY:'
    ```

    ```javascript JavaScript theme={null}
    import fetch from 'node-fetch';
    import dotenv from 'dotenv';

    dotenv.config();

    async function getPaymentDetails(paymentId) {
      const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
      
      const res = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/payments/${paymentId}`, {
        method: 'GET',
        headers: {
          'Authorization': auth,
        },
      });
      
      const data = await res.json();
      console.log('Payment status:', data.status);
      console.log('Amount:', data.request_amount);
      return data;
    }
    ```
  </CodeGroup>

  <Check>
    Confirm status is `SUCCEEDED` and amounts match your session.
  </Check>

  ## 6. Optional: Void a payment

  If needed, you can void a payment transaction:

  <CodeGroup>
    ```bash cURL theme={null}
    curl -X POST 'https://terminal-dev.xendit.co/v1/terminal/payments/PAYMENT_ID/void' \
      -u 'YOUR_TERMINAL_API_KEY:'
    ```

    ```javascript JavaScript theme={null}
    import fetch from 'node-fetch';
    import dotenv from 'dotenv';

    dotenv.config();

    async function voidPayment(paymentId) {
      const auth = 'Basic ' + Buffer.from(`${process.env.TERMINAL_API_KEY}:`).toString('base64');
      
      const res = await fetch(`${process.env.TERMINAL_BASE_URL}/v1/terminal/payments/${paymentId}/void`, {
        method: 'POST',
        headers: {
          'Authorization': auth,
        },
      });
      
      const data = await res.json();
      console.log('Void response:', data);
      return data;
    }

    // voidPayment('your-payment-id');
    ```
  </CodeGroup>

  ## Troubleshooting

  <AccordionGroup>
    <Accordion title="401 Unauthorized">
      * Ensure you include a trailing colon in the Basic Auth username encoding
      * Verify the key is a Terminal API key (not Dashboard API key)
      * Check that you're using the development base URL for testing
    </Accordion>

    <Accordion title="Simulation not working as expected">
      * Verify you're using the correct special amounts: `400508` (decline), `400509` (channel unavailable), `400711` (cancellation)
      * Check that you're in test mode (using development base URL)
      * Any `terminal_id` works for simulation - you don't need a real terminal registered
      * Normal amounts (not special test amounts) will always succeed in simulation mode
    </Accordion>

    <Accordion title="Terminal not prompting (Physical terminals only)">
      * Confirm Terminal H2H shows device as Connected/Ready
      * Verify `terminal_id` matches your device configuration exactly
      * Check network connectivity on the device
      * Ensure device has correct time settings
      * **For simulation testing**: You don't need a physical terminal - any terminal\_id will work
    </Accordion>

    <Accordion title="Webhook not receiving callbacks">
      * Use ngrok to expose your local server publicly
      * Ensure your webhook endpoint returns HTTP 200
      * Check server logs and firewall settings
      * Verify the webhook URL is configured correctly
      * **For simulation**: Callbacks work the same way as physical terminals
    </Accordion>

    <Accordion title="Environment variables not loading">
      * Verify `.env` file is in the correct location
      * Check that you're calling `dotenv.config()` before using environment variables
      * Ensure `.env` file is not committed to version control
    </Accordion>

    <Accordion title="Ready to transition from simulation to physical terminal">
      * Install and configure Terminal Gateway app or SDK
      * Register your physical terminal devices with actual Terminal IDs and IP addresses
      * Update your environment variables to use real terminal IDs
      * Test with small amounts on the physical device
      * All your existing integration code will work without changes!
    </Accordion>
  </AccordionGroup>

  ## Next steps

  Now that you have a working integration, explore these advanced features:

  <CardGroup cols={2}>
    <Card title="Terminal API (H2H) Introduction" icon="book" href="/api-reference/terminal-api/introduction">
      Complete Terminal API (H2H) documentation and reference
    </Card>

    <Card title="Terminal H2H" icon="globe" href="/sdk/h2h/introduction">
      Learn about Terminal H2H SDKs for Android and iOS
    </Card>

    <Card title="Payment Callbacks" icon="webhook" href="/api-reference/terminal-api/callbacks">
      Handle real-time payment notifications and status updates
    </Card>

    <Card title="Gateway App Configuration" icon="computer" href="/sdk/gateway/app-configuration">
      Configure Terminal Gateway app for your devices
    </Card>
  </CardGroup>

  ## Production deployment

  When ready for production:

  1. **Switch to live API keys** - Use production Terminal API key and base URL `https://terminal.xendit.co`
  2. **Update webhook URLs** - Configure production webhook endpoints that are publicly accessible
  3. **Test thoroughly** - Start with small amounts and verify all payment flows work correctly
  4. **Monitor and log** - Set up proper logging and monitoring for payment events

  <Warning>
    Always test thoroughly with small amounts in production before processing real customer payments.
  </Warning>
</div>

<div id="step3-c2c-fork" className="quickstart-content" style={{display: 'none'}}>
  <div className="wizard-step-indicator">
    <div className="wizard-step completed">
      <span className="wizard-step-dot">
        <svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>
      </span>

      <span>Integration type</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step completed">
      <span className="wizard-step-dot">
        <svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>
      </span>

      <span>Integration path</span>
    </div>

    <div className="wizard-step-divider" />

    <div className="wizard-step active">
      <span className="wizard-step-dot">3</span>
      <span>Get started</span>
    </div>
  </div>

  <div style={{ marginBottom: '24px' }}>
    <button
      className="quickstart-back-button"
      onClick={() => {
    document.getElementById('step3-c2c-fork').style.display = 'none';
    document.getElementById('step3-providers').style.display = 'block';
    window.location.hash = 'step3-providers';
  }}
    >
      <svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20">
        <path fillRule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0L3.586 10l4.707-4.707a1 1 0 011.414 1.414L6.414 10l3.293 3.293a1 1 0 010 1.414z" clipRule="evenodd" />
      </svg>

      Back to provider selection
    </button>
  </div>

  <div className="selection-banner c2c-banner">
    <svg style={{ width: '24px', height: '24px' }} fill="currentColor" viewBox="0 0 20 20">
      <path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
    </svg>

    <div>
      <h3 style={{ margin: '0', fontWeight: '600' }}>Choose your C2C interface</h3>
      <p style={{ margin: '0', opacity: '0.8' }}>Terminal C2C API (HTTP) or Terminal C2C SDK (native methods)</p>
    </div>
  </div>

  <div className="quickstart-elevated">
    <table className="quickstart-table">
      <thead>
        <tr>
          <th className="quickstart-table-heading blue" style={{ width: '50%' }}>
            <div style={{ fontWeight: '700', marginBottom: '4px' }}>Terminal C2C API</div>
            <div>HTTP REST commands</div>
          </th>

          <th className="quickstart-table-heading neutral" style={{ width: '50%' }}>
            <div style={{ fontWeight: '700', marginBottom: '4px' }}>Terminal C2C SDK</div>
            <div>Native SDK method calls</div>
          </th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td className="quickstart-table-cell blue">
            Send REST commands (PAY, CANCEL, SETTLEMENT) to the Gateway App over the local network.
          </td>

          <td className="quickstart-table-cell">
            Call native Android/iOS SDK methods to talk to terminals directly from your app.
          </td>
        </tr>

        <tr>
          <td className="quickstart-table-cell blue">
            Best for multi-store fleets, web POS, or thick-client systems that call backend services.
          </td>

          <td className="quickstart-table-cell">
            Ideal for kiosks, custom POS apps, or deployments that need offline resilience and custom UX.
          </td>
        </tr>

        <tr>
          <td className="quickstart-table-cell blue">
            Works from any language or platform that can make HTTP requests.
          </td>

          <td className="quickstart-table-cell">
            Requires mobile engineers but unlocks granular device telemetry and fallback logic.
          </td>
        </tr>
      </tbody>
    </table>

    <div className="wizard-button-grid">
      <button
        className="wizard-button-primary blue"
        onClick={() => {
      document.getElementById('step3-c2c-fork').style.display = 'none';
      document.getElementById('step3-c2c-api-content').style.display = 'block';
      window.location.hash = 'step3-c2c-api-content';
    }}
      >
        <svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
        </svg>

        Continue with Terminal C2C API
      </button>

      <button
        className="wizard-button-secondary"
        onClick={() => {
      document.getElementById('step3-c2c-fork').style.display = 'none';
      document.getElementById('step3-c2c-sdk-content').style.display = 'block';
      if (window.updateC2CProviderSnippets) window.updateC2CProviderSnippets();
      window.location.hash = 'step3-c2c-sdk-content';
    }}
      >
        <svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
        </svg>

        Continue with Terminal C2C SDK
      </button>
    </div>
  </div>
</div>

<div id="step3-c2c-api-content" className="quickstart-content" style={{display: 'none'}}>
  <Info>
    You've chosen the **Terminal C2C API** — HTTP REST commands sent over the local network.
  </Info>

  <div style={{ marginBottom: '24px' }}>
    <a href="/api-reference/c2c/introduction" className="quickstart-link-card">
      <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
        <div>📖</div>

        <div>
          <div style={{ fontWeight: '600', marginBottom: '4px' }}>Terminal C2C API Reference</div>
          <div>Complete C2C API documentation and endpoints</div>
        </div>
      </div>
    </a>
  </div>

  ## Prerequisites

  * Gateway App installed and configured
  * Access to C2C API credentials and endpoints
  * Terminal device details: [Terminal ID (TID)](/sdk/gateway/app-configuration#finding-terminal-information) and [IP address](/sdk/gateway/app-configuration#finding-terminal-information)

  <Info>
    In C2C API mode, your system communicates with terminals via the Gateway App and REST endpoints. Set up the Gateway App first, then follow the API guide.
  </Info>

  ## Steps

  <Steps>
    <Step title="Install and configure the Gateway App">
      Follow the Gateway App setup guide:

      * [Gateway App Setup](/sdk/gateway/app-configuration)
    </Step>

    <Step title="Confirm terminal device information">
      Collect the [Terminal ID (TID)](/sdk/gateway/app-configuration#finding-terminal-information) and [IP address](/sdk/gateway/app-configuration#finding-terminal-information) for each device you’ll use.
    </Step>

    <Step title="Integrate using the C2C API">
      Implement the REST API integration:

      * [C2C API Reference](/api-reference/c2c/introduction)

      ```bash Create a payment request theme={null}
      curl -X POST "http://{GATEWAY_IP}:8189/commands/pay" \
        -H "Content-Type: application/json" \
        -H "X-API-KEY: CLIENT_API_KEY" \
        -H "provider: BRI" \
        -H "simulation: true" \
        -d '{
          "terminal_id": "10362517",
          "order_id": "ORDER123",
          "request_amount": 10000,
          "payment_method": "QRIS"
        }'
      ```

      <Info>
        Using `simulation: true` returns mock responses so you can test without a physical device. Remove the header when exercising real hardware; the value defaults to `false`.
      </Info>

      ```json Successful response theme={null}
      {
        "order_id": "ORDER123",
        "terminal_id": "10362517",
        "terminal_reference": "1750407594445|1750407594",
        "payment_method": "QRIS",
        "amount": 10000,
        "currency": "IDR",
        "transaction_date": "2025-06-20T15:19:54+07:00",
        "status": "SUCCESS"
      }
      ```
    </Step>
  </Steps>

  <Check>
    You’re ready to send API requests through the Gateway App to the terminal devices you configured.
  </Check>

  <h2>Troubleshooting</h2>

  <AccordionGroup>
    <Accordion title="Gateway App not responding">
      * Confirm the Gateway App is running on the same network segment as your POS.
      * Check that the device IP and port are reachable (default 8189).
      * Restart the Gateway App after changing provider credentials or API keys.
    </Accordion>

    <Accordion title="401 or 403 errors from C2C API">
      * Verify you are using the Gateway App API key rather than your Dashboard key.
      * Include the correct provider header (BRI, NTT, CASHUP, or SHC) with each request.
      * Regenerate the Gateway App credentials if the key rotation recently occurred.
    </Accordion>

    <Accordion title="Terminal does not prompt for payment">
      * Ensure the terminal is registered in the Gateway App with the exact terminal ID (TID).
      * Confirm the device shows Connected/Ready status in the Gateway App UI.
      * Recheck network connectivity and firewall rules that might block terminal traffic.
    </Accordion>
  </AccordionGroup>

  <h2>Next steps</h2>

  <CardGroup cols={2}>
    <Card title="Terminal C2C API Reference" icon="book" href="/api-reference/c2c/introduction">
      Dive deeper into payload formats, error codes, and advanced operations.
    </Card>

    <Card title="Gateway App Operations" icon="computer" href="/sdk/gateway/app-configuration">
      Learn how to monitor device fleets and rotate credentials safely.
    </Card>

    <Card title="Terminal API (H2H)" icon="globe" href="/api-reference/terminal-api/introduction">
      Compare with the managed H2H flow if you later need centralized orchestration.
    </Card>
  </CardGroup>

  <h2>Production deployment</h2>

  <ol>
    <li>Switch the Gateway App to production mode and provision production API keys.</li>
    <li>Whitelist production terminal IPs and ensure secure TLS termination on your POS.</li>
    <li>Run end-to-end tests with small live amounts before opening to staff.</li>
    <li>Set up monitoring for Gateway App health, API latency, and payment callbacks.</li>
  </ol>
</div>

<div id="step3-c2c-sdk-content" className="quickstart-content" style={{display: 'none'}}>
  <Info>
    You've chosen the **Terminal C2C SDK** — native Android/iOS method calls for direct terminal communication.
  </Info>

  <div style={{ marginBottom: '24px' }}>
    <a href="/sdk/c2c/android-sdk" className="quickstart-link-card">
      <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
        <div>🤖</div>

        <div>
          <div style={{ fontWeight: '600', marginBottom: '4px' }}>Android C2C SDK</div>
          <div>Complete Android C2C SDK integration guide</div>
        </div>
      </div>
    </a>
  </div>

  <div style={{ marginBottom: '24px' }}>
    <a href="/sdk/c2c/ios-sdk" className="quickstart-link-card">
      <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
        <div>🍎</div>

        <div>
          <div style={{ fontWeight: '600', marginBottom: '4px' }}>iOS C2C SDK</div>
          <div>Complete iOS C2C SDK integration guide</div>
        </div>
      </div>
    </a>
  </div>

  ## Prerequisites

  * Terminal C2C SDK added to your app (Android or iOS)
  * Network connectivity to the terminal devices
  * Terminal device details: [Terminal ID (TID)](/sdk/gateway/app-configuration#finding-terminal-information) and [IP address](/sdk/gateway/app-configuration#finding-terminal-information)

  <Info>
    In C2C SDK mode, your app talks directly to the terminal devices using platform SDKs (no Gateway App required).
  </Info>

  ## Steps

  <Steps>
    <Step title="Add provider dependencies">
      Include the provider-specific artifacts before initializing the SDK. Select the providers above to populate the correct entries.

      <Tabs>
        <Tab title="Android (Gradle)">
          <div id="c2c-android-dependency-snippet">
            ```groovy theme={null}
            dependencies {
              // Terminal C2C SDK
              implementation("co.xendit.terminal:c2c-android:<latest_version>")

              // Core Terminal SDK (required)
              implementation("co.xendit.terminal:core-android:<latest_version>")

              implementation("co.xendit.terminal:id-bri-android:<latest_version>")
            }
            ```
          </div>
        </Tab>

        <Tab title="iOS (Frameworks)">
          <div id="c2c-ios-dependency-snippet">
            ```text theme={null}
            # Add these provider frameworks using Xcode (General > Frameworks, Libraries, and Embedded Content).
            # See /sdk/c2c/ios-sdk#installation for installation steps.

            - Add TerminalBRI.xcframework via Xcode (General > Frameworks, Libraries, and Embedded Content). Follow /sdk/c2c/ios-sdk#installation.
            ```
          </div>
        </Tab>
      </Tabs>
    </Step>

    <Step title="Install and set up the C2C SDK">
      <Tabs>
        <Tab title="Android (Kotlin)">
          <div id="c2c-android-provider-snippet">
            ```kotlin theme={null}
            import co.xendit.terminal.c2c.TerminalC2C
            import co.xendit.terminal.core.TerminalApp

            class App : Application() {
              override fun onCreate() {
                super.onCreate()

                TerminalApp.initialize(
                  context = this,
                  clientKey = CLIENT_KEY,
                  mode = TerminalMode.LIVE // or TerminalMode.INTEGRATION
                )
                TerminalC2C.addProvider(TerminalBRI)
              }
            }
            ```
          </div>
        </Tab>

        <Tab title="iOS (Swift)">
          <div id="c2c-ios-provider-snippet">
            ```swift theme={null}
            import TerminalC2C

            func application(
              _ application: UIApplication,
              didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
            ) -> Bool {
              TerminalApp.shared.initialize(
                clientKey: CLIENT_KEY,
                mode: TerminalMode.live // or TerminalMode.integration
              )
              TerminalC2C.shared.addProvider(provider: TerminalBRI.shared)
              return true
            }
            ```
          </div>
        </Tab>
      </Tabs>
    </Step>

    <Step title="Configure the terminal device in your app">
      Configure each device using its [Terminal ID (TID)](/sdk/gateway/app-configuration#finding-terminal-information) and [IP address](/sdk/gateway/app-configuration#finding-terminal-information).

      <Tabs>
        <Tab title="Android (Kotlin)">
          <div id="c2c-android-device-snippet">
            ```kotlin theme={null}
            val terminalDevice = TerminalDevice.create(
              id = "TID001",
              ipAddress = "192.168.1.100",
              provider = "BRI"
            )

            TerminalC2C.setTerminalDevice(terminalDevice)
            ```
          </div>
        </Tab>

        <Tab title="iOS (Swift)">
          <div id="c2c-ios-device-snippet">
            ```swift theme={null}
            let terminalDevice = TerminalDevice.companion.create(
              id: "TID001",
              ipAddress: "192.168.1.100",
              provider: "BRI"
            )

            TerminalC2C.shared.setTerminalDevice(terminalDevice)
            ```
          </div>
        </Tab>
      </Tabs>
    </Step>

    <Step title="Run a test transaction">
      Use the SDK “Getting Started” steps for your platform to trigger a basic flow and confirm the device responds correctly.

      <Tabs>
        <Tab title="Android (Kotlin)">
          ```kotlin theme={null}
          import co.xendit.terminal.c2c.TerminalC2C
          import co.xendit.terminal.c2c.data.Payment
          import co.xendit.terminal.c2c.data.TerminalException
          import co.xendit.terminal.id.bri.BRIPaymentMethod // Provided by the BRI provider dependency

          // Create payment data
          val payment = Payment(
            orderID = "ORDER_123",
            amount = 10000.0,
            paymentMethod = BRIPaymentMethod.contactless
          )

          // Execute payment (suspend function)
          try {
            val result = TerminalC2C.createPayment(
              payment = payment,
              isSimulation = true // Remove or set to false when using a physical terminal
            )
            println("Payment successful: ${'$'}{result.status}")
          } catch (e: TerminalException) {
            println("Payment failed: ${'$'}{e.message}")
          } catch (e: Exception) {
            println("Error: ${'$'}{e.message}")
          }
          ```
        </Tab>

        <Tab title="iOS (Swift)">
          ```swift theme={null}
          import TerminalC2C

          // Create payment data
          let payment = Payment(
            orderID: "ORDER_123",
            amount: 10000.0,
            paymentMethod: BRIPaymentMethod.contactless
          )

          // Execute payment
          Task {
            do {
              let result = try await TerminalC2C.shared.createPayment(
                payment: payment,
                isSimulation: true // Remove or set to false when using a physical terminal
              )
              print("Payment successful: \(result.status)")
            } catch let error as TerminalException {
              print("Payment failed: \(error.message)")
            } catch {
              print("Error: \(error.localizedDescription)")
            }
          }
          ```
        </Tab>
      </Tabs>

      <Info>
        For SDK testing without hardware, either set `TerminalC2C.isSimulation = true` globally before issuing requests or pass `isSimulation = true` to individual calls as shown above. Remove these simulation flags for real terminal runs.
      </Info>
    </Step>
  </Steps>

  <Check>
    If your test succeeds, your app is ready to communicate with the terminal using the C2C SDK.
  </Check>

  <script type="text/javascript">
    {`
        setTimeout(function() {
          if (window.updateC2CProviderSnippets) {
            window.updateC2CProviderSnippets();
            setTimeout(window.updateC2CProviderSnippets, 250);
          }
          if (window.updateH2HProviderSnippets) {
            window.updateH2HProviderSnippets();
            setTimeout(window.updateH2HProviderSnippets, 250);
          }
        }, 0);
        `}
  </script>

  <h2>Troubleshooting</h2>

  <AccordionGroup>
    <Accordion title="SDK initialization fails">
      * Confirm the Client Key matches the environment (sandbox vs production).
      * Initialize the SDK during application start before invoking any payment calls.
      * Add required permissions (BLE, network) to your AndroidManifest or Info.plist.
    </Accordion>

    <Accordion title="Terminal remains offline">
      * Check that the terminal device IP is reachable from the mobile device.
      * Verify the provider SDK (BRI, NTT, Cashup, SHC) is registered before setting the device.
      * Recreate the terminal pairing if the device was rebooted or network changed.
    </Accordion>

    <Accordion title="Payment command returns errors">
      * Inspect the SDK error object for provider-specific codes and retry guidance.
      * Ensure amount, currency, and payment method align with the provider's supported values.
      * For persistent failures, fall back to the Terminal C2C API mode and compare payloads.
    </Accordion>
  </AccordionGroup>

  <h2>Next steps</h2>

  <CardGroup cols={2}>
    <Card title="Android SDK Deep Dive" icon="code" href="/sdk/c2c/android-sdk">
      Explore lifecycle hooks, receipt printing, and advanced device management.
    </Card>

    <Card title="iOS SDK Deep Dive" icon="code" href="/sdk/c2c/ios-sdk">
      Review concurrency patterns, error domains, and background execution rules.
    </Card>

    <Card title="Migration Guidance" icon="arrow-right" href="/guides/migration/xen-bri-to-h2h">
      Plan future transitions between C2C and H2H solutions.
    </Card>
  </CardGroup>

  <h2>Production deployment</h2>

  <ol>
    <li>Embed secure storage for client keys and rotate them on schedule.</li>
    <li>Enable crash and telemetry reporting for SDK interactions and payment outcomes.</li>
    <li>Run pilot stores with real terminals before rolling out widely.</li>
    <li>Document recovery flows so field teams can re-pair or reset devices quickly.</li>
  </ol>
</div>
