# API keys & IP allowlist

API keys are how your server authenticates to the public Kwik Nkap Payments API. You create and manage them in the dashboard Developers section, and you can optionally restrict which source IPs are allowed to use them with an IP allowlist. This page covers creating keys, the `kn_sk_test_` / `kn_sk_live_` prefixes, rotation and revocation, and the per-business IP allowlist.

For how the key is sent on a request, see [Authentication](/en/payments/authentication).

## Creating a key

Keys are created in the dashboard, not through the API.

1. Open the dashboard at [app.kwiknkap.com](https://app.kwiknkap.com) and go to the **Developers** section.
2. Choose the environment with the Sandbox / Live toggle. The environment you pick decides the key prefix and the database the key authenticates against.
3. Give the key a name and create it. The full secret is shown **once** in a copy-once dialog. Copy it and store it somewhere safe immediately.

Kwik Nkap stores only a hash of the key plus a short prefix preview, so the dashboard can show you which key is which but can never reveal the full secret again. If you lose it, you create a new one.

:::warning
The plaintext secret is displayed only at creation time and is stored hashed. There is no way to retrieve it later. If you did not copy it, revoke the key and create a new one.
:::

## Key prefixes and environments

There is exactly one secret key per environment. The prefix encodes which environment the key belongs to, and sandbox and live are completely separate databases.

| Prefix | Environment | Calls hit |
| --- | --- | --- |
| `kn_sk_test_…` | Sandbox | Simulated outcomes, no real phone prompt, separate database |
| `kn_sk_live_…` | Live | Real Mobile Money debits against the customer's wallet |

Because the prefix selects the environment, you never send an environment flag with your request. The key alone determines whether a call runs in sandbox or live. Test thoroughly with a `kn_sk_test_` key, then swap in your `kn_sk_live_` key to go live. See [Testing](/en/payments/testing) for the sandbox flow and the guaranteed-outcome test phone numbers.

:::note
There is no publishable key and no Stripe-style `sk_` / `pk_` pair. Kwik Nkap uses a single secret key per environment, sent server-side only.
:::

## Rotating a key

Rotating means issuing a new key and retiring the old one, without downtime:

1. Create a new key for the same environment in the Developers section.
2. Deploy the new secret to your servers (update your environment variable or secret store).
3. Confirm live traffic is authenticating with the new key.
4. Revoke the old key.

Rotate on a schedule, and immediately if a key may have leaked (committed to a repo, pasted into a log, shared in a ticket).

## Revoking a key

Revoking a key deactivates it immediately. Any request presenting a revoked key is rejected with `401 Unauthorized`. Revocation cannot be undone, so if you revoke a key still in use, replace it first or rotate as described above.

## IP allowlist

The IP allowlist is an optional, per-business control that restricts which source IPs may call the public API. You manage it in the dashboard by adding CIDR ranges.

How it behaves:

- **Empty allowlist (default):** all source IPs are allowed. Your keys work from anywhere.
- **One or more active entries:** only requests whose source IP matches an allowlisted CIDR range are accepted. Every other source IP is rejected with `403 Forbidden`.

Add your production server's egress IP (or its CIDR block) before relying on the allowlist, otherwise you will lock yourself out. The allowlist applies to the whole business across both environments, so make sure every server that calls the API is covered.

```text title="Example CIDR entries"
203.0.113.42/32      # a single static IP
198.51.100.0/24      # a whole /24 block
```

| Behavior | Result |
| --- | --- |
| No active entries | All IPs allowed |
| Source IP matches an active entry | Request proceeds to key validation |
| Source IP matches no active entry | `403 Forbidden` |

:::caution
A `403` from an IP that should be allowed almost always means that source IP is not covered by an allowlist entry. Check your server's real egress IP (it may differ from the host's public IP behind NAT or a proxy) and add the correct CIDR.
:::

## Security best practices

:::tip
- Treat each key like a password. It can move real money in the live environment.
- Use keys server-side only. Never ship a key in frontend code, a mobile app, or anything that reaches the browser.
- Store keys in a secret manager or environment variable, never in source control.
- Use the `kn_sk_test_` key for all development and CI; reserve the `kn_sk_live_` key for production.
- Rotate keys periodically, and immediately if one may have been exposed.
- Turn on the IP allowlist in production to limit valid keys to your known servers.
- Keep one key per environment and give it a clear name so it is easy to rotate or revoke.
:::

## Next steps

- [Authentication](/en/payments/authentication) — sending the key with the `X-API-Key` header.
- [Webhooks](/en/payments/webhooks) — receive `payment.success` and `payment.failed` events and verify their signatures.
