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

# Quickstart

> First payment in 10 minutes

Two paths depending on your style:

<Tabs>
  <Tab title="Stack Builder (recommended)">
    <Note>
      **10 minutes**, zero copy-paste code. Fill in your keys inside SandPay, download a pre-filled starter zip, and run `./setup.sh`. Works on macOS, Linux, and Windows.
    </Note>

    <Steps>
      <Step title="Create a SandPay account">
        Sign up at [sandpay.dev/sign-up](https://sandpay.dev/sign-up). Onboarding takes \~30 seconds: email, password, first operator.
      </Step>

      <Step title="Generate an API key">
        Go to `/settings → API keys → Create new key`. The `sp_sk_test_…` key is shown only once — keep the tab open to carry it into step 3 without having to retype it.
      </Step>

      <Step title="Choose your stack">
        Click **"Open Integration guide with this key →"** in the modal, or navigate manually to `/integration` (in the sidebar, under **Dev → Integration**). The **Stack Builder** page lists 5 backends and 4 mobile clients. Select:

        * **One backend** from: Supabase Edge Functions, Next.js API Routes, Express, Hono, FastAPI
        * **Zero or more clients**: Next.js web, Flutter, React Native, iOS native, Android native

        Fill in your project-specific values (Supabase URL/anon/service-role if applicable, custom port, project name). Enable the **"Include my secrets in .env"** toggle if you want the zip ready to use (security note: the zip will then contain secrets in plain text — treat it like a password manager export).
      </Step>

      <Step title="Download and run">
        Click **"Download zana-app.zip"**. Unzip, then:

        <CodeGroup>
          ```bash macOS / Linux theme={null}
          unzip zana-app.zip
          cd zana-app
          ./setup.sh
          ```

          ```powershell Windows theme={null}
          Expand-Archive zana-app.zip
          cd zana-app
          .\setup.ps1
          ```
        </CodeGroup>

        The script confirms your values (or prompts for them if you didn't enable secret inclusion), then writes the `.env` files in the right places. Follow the displayed commands to deploy Supabase, start the backend, start the frontend, and start the mobile app.
      </Step>

      <Step title="First payment">
        From your web or mobile app, trigger a test payment:

        * Number: `+250788123456` (default Rwanda MTN)
        * Amount: `25000`
        * Reference: `ORDER-TEST-001`

        You receive a synchronous `status: SUCCESS`, then the `payment.completed` webhook asynchronously a few seconds later with the synthesised operator `raw` field — it faithfully reproduces the native MTN/Orange/Moov/Airtel shape (with `_simulated: true` at the top level).
      </Step>
    </Steps>

    <Accordion title="Testing locally with Supabase (Edge Functions)">
      Two modes, depending on whether you want to use Docker. The full details
      (and the network direction table) are in the starter's `README.md`.

      * **Option A — Full local (Docker required).** `supabase start` runs everything on
        your machine, then `supabase functions serve --env-file supabase/.env`.
        ⚠️ Gotcha: an Edge Function runs **inside a Docker container**, so
        `localhost` refers to the container, not your machine. To reach SandPay
        (on the host at `localhost:3800`), the function must use
        **`http://host.docker.internal:3800`**. Clients point at local Supabase
        (`http://127.0.0.1:54321`); the SandPay webhook points at
        `http://localhost:54321/functions/v1/sandpay-webhook`. (On an Android
        emulator, the host is reached via `10.0.2.2`, not `127.0.0.1`.)
      * **Option B — Mixed (cloud functions + local clients, no Docker).** Edge
        Functions stay on Supabase cloud; your clients run locally.
        The cloud cannot reach your `localhost:3800`, so expose SandPay
        via **ngrok with a reserved static domain** (free, 1 domain):
        `ngrok http 3800 --domain=your-name.ngrok-free.app`, then
        `supabase secrets set SANDPAY_BASE_URL=https://your-name.ngrok-free.app`.
        Advantage: the URL **stays the same** across restarts → set the
        secret **once**. (`cloudflared` quick-tunnels and `ngrok http`
        without `--domain` rotate the URL on every restart — avoid them.) The
        webhook then points at the cloud function.
    </Accordion>

    <Tip>
      The starter zip is OS-aware: executable bit preserved on `.sh`, LF line endings on Linux/macOS and CRLF on PowerShell. The `setup.sh` script also auto-detects `bash`, `zsh`, or `sh`.
    </Tip>
  </Tab>

  <Tab title="Manual integration">
    For developers who want to understand every piece, or who have an atypical infrastructure.

    <Steps>
      <Step title="Create a SandPay account">
        Go to [sandpay.dev/sign-up](https://sandpay.dev/sign-up) and create your organisation. Onboarding has 4 steps: profile, organisation, first operator, verification.
      </Step>

      <Step title="Connect an operator">
        At step 3 of onboarding (or later from `/settings`), choose an operator and country — for example **Orange Côte d'Ivoire**. In sandbox mode you can use test credentials: no network calls are made if you stay in simulation. See the [operator guides](/en/operators/mtn) for per-portal details.
      </Step>

      <Step title="Get your API key">
        From `/settings/api-keys`, create a key. It looks like `sp_sk_test_a1b2c3d4...`. Copy it immediately — the full value is shown only once.
      </Step>

      <Step title="First payment">
        Send your first `POST /v1/payments` request:

        <CodeGroup>
          ```bash curl theme={null}
          curl -X POST https://api.sandpay.dev/v1/payments \
            -H "Authorization: Bearer $SANDPAY_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "amount": 25000,
              "currency": "FCFA",
              "operator": "orange",
              "country": "CI",
              "msisdn": "+22507123456",
              "reference": "ORDER-2026-A1",
              "scenario": "success"
            }'
          ```

          ```ts Node SDK theme={null}
          import { SandPay } from "@drwintech/sandpay";

          const sp = new SandPay({ apiKey: process.env.SANDPAY_API_KEY! });

          const tx = await sp.payments.create({
            amount: 25000,
            currency: "FCFA",
            operator: "orange",
            country: "CI",
            msisdn: "+22507123456",
            reference: "ORDER-2026-A1",
            scenario: "success",
          });

          console.log(tx.id, tx.status);
          ```
        </CodeGroup>

        Expected response:

        ```json theme={null}
        {
          "id": "TX_8K3M9F",
          "amount": 25000,
          "currency": "FCFA",
          "operator": "orange",
          "country": "CI",
          "msisdn": "+22507123456",
          "reference": "ORDER-2026-A1",
          "scenario": "success",
          "status": "SUCCESS",
          "latencyMs": 1240,
          "createdAt": "2026-05-23T10:14:02.412Z"
        }
        ```
      </Step>
    </Steps>

    <Note>
      The `scenario` field is optional. Without an explicit value, SandPay applies `success`. To exercise failure paths, see the [scenarios reference](/en/scenarios). To integrate into a real app, see [Webhooks](/en/webhooks) for receiving async statuses, and [SDKs](/en/sdks/node) for per-stack examples.
    </Note>
  </Tab>
</Tabs>

## Next steps

<Tip>
  For a complete integration (full contract, statuses, commission, webhooks,
  recommended architecture), the canonical reference — **the source of truth** —
  is the [**Integration Guide**](/en/integration-guide).
</Tip>

<CardGroup cols={2}>
  <Card title="Integration Guide" icon="book" href="/integration-guide">
    The full end-to-end contract — the canonical reference.
  </Card>

  <Card title="Configure webhooks" icon="webhook" href="/webhooks">
    Receive async transaction statuses with HMAC signature verification.
  </Card>

  <Card title="All scenarios" icon="list" href="/scenarios">
    10 simulation scenarios for testing every operator error case.
  </Card>

  <Card title="Operator guides" icon="phone" href="/operators/mtn">
    MTN, Orange, Moov, Airtel specifics.
  </Card>

  <Card title="Node.js SDK" icon="code" href="/sdks/node">
    @drwintech/sandpay — full types, webhook helpers.
  </Card>

  <Card title="FAQ & integration tips" icon="circle-question" href="/integration-faq">
    Webhook not firing locally, commission/`net_amount`, reconciliation — the questions you actually run into.
  </Card>
</CardGroup>
