# Get started

<Head>
  <link rel="canonical" href="https://docs.kwiknkap.com/en/getting-started" />
  <meta property="og:type" content="article" />
  <meta property="og:site_name" content="Kwik Nkap" />
  <meta property="og:title" content="Get started with the Kwik Nkap API" />
  <meta property="og:description" content="Account, sandbox key, first Mobile Money payment. Three steps, about ten minutes." />
  <link rel="alternate" hrefLang="fr" href="https://docs.kwiknkap.com/fr/getting-started" />
  <link rel="alternate" hrefLang="en" href="https://docs.kwiknkap.com/en/getting-started" />
  <script type="application/ld+json">
    {JSON.stringify({
      "@context": "https://schema.org",
      "@type": "HowTo",
      name: "Take your first Kwik Nkap payment",
      totalTime: "PT10M",
      step: [
        { "@type": "HowToStep", name: "Create your account", url: "https://docs.kwiknkap.com/en/getting-started#create-your-account" },
        { "@type": "HowToStep", name: "Get a sandbox API key", url: "https://docs.kwiknkap.com/en/getting-started#get-a-sandbox-api-key" },
        { "@type": "HowToStep", name: "Collect your first payment", url: "https://docs.kwiknkap.com/en/getting-started#collect-your-first-payment" },
      ],
    })}
  </script>
</Head>

About ten minutes, and nothing to install. You need a phone number that can receive an MTN MoMo or Orange Money prompt — in sandbox that can be any number, because nothing real is charged.

<Stepper>

1. ### Create your account

   Sign up at [app.kwiknkap.com](https://app.kwiknkap.com) with your phone number and email, then create your business profile: name, category, and the phone number money settles to.

   **You can build immediately.** Sandbox works the moment the account exists — verification is not a gate on development, only on live money.

   Start [identity and business verification](/en/products/kyc) now anyway, because it takes days rather than minutes and it is what unlocks `kn_sk_live_` keys. Doing it in parallel with your integration means you are not waiting on it at the end.

   ✅ **You should now see** the dashboard, with a Developers section in the sidebar.

2. ### Get a sandbox API key

   In **Developers → API keys**, create a key. Choose the scopes it needs and nothing more — for a checkout server that is `payments:write` and `payments:read`, which is enough to take money and read back status, and not enough to touch invoices or send anything. See [Scopes](/en/concepts/scopes).

   The key is shown **once**. Put it in your server's environment straight away:

   ```bash title=".env"
   KWIKNKAP_API_KEY=kn_sk_test_...
   ```

   Your key's prefix is the environment. `kn_sk_test_` reaches sandbox; `kn_sk_live_` reaches live and moves real money. There is no environment header to get wrong — see [Environments and API keys](/en/concepts/environments-and-keys).

   :::warning
   A secret key is a bearer credential. Never put it in a mobile app, a browser bundle, or a repository. Anything prefixed `VITE_` or `NEXT_PUBLIC_` is compiled into the client bundle, which is the most common way a key becomes public.
   :::

   ✅ **You should now see** a key beginning `kn_sk_test_`, stored somewhere your server can read and your repository cannot.

3. ### Collect your first payment

   Charge a wallet. The `Idempotency-Key` means a network retry cannot charge twice — [why that matters](/en/concepts/idempotency).

   ```bash title="Create a payment"
   curl -X POST https://api.kwiknkap.com/v1/payments \
     -H "X-API-Key: $KWIKNKAP_API_KEY" \
     -H "Idempotency-Key: $(uuidgen)" \
     -H "Content-Type: application/json" \
     -d '{
       "amount": 5000,
       "phone_number": "237670000001",
       "payment_method": "mobile_money"
     }'
   ```

   ```json title="201 Created"
   {
     "id": "knpay_test_9f2c41a7b8e04d6fa1c3e58b7d92f014",
     "status": "PENDING",
     "amount": 5000,
     "currency": "XAF",
     "payment_method": "mobile_money",
     "environment": "SANDBOX"
   }
   ```

   **`PENDING` is the correct answer, and it is not "paid".** The customer has been prompted on their phone and has not decided yet. Read [How a payment works](/en/concepts/how-payments-work) before you write the code that acts on this — it is the single most expensive misunderstanding in this API.

   ✅ **You should now see** a `201` with `status: PENDING` and an id beginning `knpay_test_`.

4. ### Find out what happened

   Poll while you are developing:

   ```bash title="Check the status"
   curl https://api.kwiknkap.com/v1/payments/knpay_test_9f2c41a7b8e04d6fa1c3e58b7d92f014/status \
     -H "X-API-Key: $KWIKNKAP_API_KEY"
   ```

   In production, take the outcome from a [webhook](/en/payments/webhooks) instead: it arrives the moment the payment resolves, is signed so you can trust it, and is retried for three days if your endpoint is down.

   A `FAILED` payment carries a [`failure_code`](/en/concepts/errors) you can act on. `insufficient_funds` is worth retrying after the customer tops up; `customer_account_issue` is not.

   ✅ **You should now see** the payment settle to `SUCCESS` or `FAILED`, with a failure code if it failed.

5. ### Go live

   Before switching the prefix:

   - **Verification approved** — no `kn_sk_live_` key exists until it is.
   - **You fulfil on the transition into `SUCCESS`**, never on seeing it, so a duplicate webhook cannot ship twice. [How](/en/concepts/payment-states).
   - **Every create call sends an `Idempotency-Key`.**
   - **Your webhook endpoint verifies signatures** and answers `2xx` in under a few seconds.
   - **You have triggered a real failure in sandbox** and shown your customer something useful. [Testing](/en/payments/testing).
   - **Live keys are scoped** to what that consumer actually does, and are not in your repository.

   Then mint a `kn_sk_live_` key, swap the environment variable, and deploy. Nothing else changes: same URL, same payloads, same codes.

</Stepper>

## Where to go next

- [How a payment works](/en/concepts/how-payments-work) — the concept everything else depends on
- [Choosing how to collect](/en/collections/overview) — direct charge, payment link, invoice or storefront
- [Managing API keys](/en/payments/api-keys) — rotation, revocation and IP allowlisting
- [Build with an AI agent](/en/build-with-ai) — if you are integrating with Claude Code, Codex or Cursor
