# Payments & collections

Collections are Kwik Nkap's one public, developer-facing product. You create a collection, the customer approves the debit on their handset, and the payment settles to `SUCCESS` or `FAILED`. This page explains the concept, the surface, and the lifecycle. The how-to pages cover each step in depth.

## What a collection is

A **collection** is a pull payment. Your server asks Kwik Nkap to debit a specific amount from a customer's Mobile Money wallet (MTN MoMo or Orange Money), and Kwik Nkap pulls the funds into your merchant balance once the customer approves on their phone.

You never touch card numbers or wallet PINs. You supply three things: an `amount` in XAF, the customer's `phone_number`, and the `operator`. The customer authorizes the debit with their Mobile Money PIN on their own handset. Kwik Nkap handles the provider rails behind that.

:::info
Amounts are whole XAF francs. `amount` is an integer with a minimum of `1` — no minor units, no multiply-by-100. `1000` means 1,000 XAF. Currency is always `XAF` and is set server-side, so it is not a field you send.
:::

## The public surface

The entire public API is three endpoints on the payment gateway. There is nothing else to learn.

| Method | Path | Purpose |
| --- | --- | --- |
| `POST` | `/v1/payments` | Create a collection (the pull payment) |
| `GET` | `/v1/payments` | List payments (filter by `status`, page with `limit`/`offset`) |
| `GET` | `/v1/payments/{paymentId}/status` | Retrieve a single payment's status |

All requests go to the base URL:

<ApiBaseUrl />

Every call authenticates with your API key in the `X-API-Key` header. The key prefix selects the environment: `kn_sk_test_…` hits sandbox, `kn_sk_live_…` hits live. There is one secret key per environment — no publishable key, no Stripe-style key pair. See [Authentication](/en/payments/authentication) for the full model.

## The collection lifecycle

A collection moves through a small, predictable set of states.

<Mermaid chart={`
sequenceDiagram
    participant M as Your server
    participant K as Kwik Nkap
    participant C as Customer phone
    M->>K: POST /v1/payments
    K-->>M: 201 { status: PENDING }
    K->>C: Mobile Money prompt
    C->>K: Approve with PIN
    K-->>M: webhook payment.success / payment.failed
    Note over M,K: or poll GET /payments/{id}/status
`} />

1. **Create.** You `POST /v1/payments`. Kwik Nkap creates the payment as `PENDING` and triggers a Mobile Money prompt on the customer's phone.
2. **Customer approves.** The customer sees an MTN MoMo or Orange Money prompt on their handset and enters their Mobile Money PIN to approve the debit.
3. **Settle.** The provider confirms or declines. The payment becomes `SUCCESS` (funds pulled, your balance credited net of fees) or `FAILED` (no money moved).

The `POST` returns immediately with `status: "PENDING"` — settlement is asynchronous, so the create response is never the final word.

```json title="201 Created"
{
  "id": "knpay_test_9f2c41a7b8e04d6fa1c3e58b7d92f014",
  "status": "PENDING",
  "amount": 25000,
  "currency": "XAF",
  "payment_method": "mobile_money",
  "environment": "SANDBOX",
  "created_at": "2026-06-19T10:24:00Z",
  "internal_transaction_id": "...",
  "phone_number": "670123456",
  "payment_method": "mobile_money"
}
```

The full status enum (uppercase) is `PENDING`, `SUCCESS`, `FAILED`, and `UNSPECIFIED`. Payment IDs are prefixed `knpay_` in live and `knpay_test_` in sandbox.

You learn the outcome in one of three ways:

- **Webhooks** (preferred). Register an endpoint in the dashboard and receive a signed `payment.success` or `payment.failed` event the moment a collection settles. See [Webhooks](/en/payments/webhooks).
- **Poll the status endpoint.** `GET /v1/payments/{paymentId}/status`. See [Payment status](/en/api/direct-payments).
- **List payments.** `GET /v1/payments?status=SUCCESS` to sweep recent results.

:::tip
Use webhooks for the source of truth and polling as a fallback. Polling a `PENDING` payment in a tight loop wastes your rate budget; a webhook tells you the instant it settles.
:::

## Operators and providers

You name the customer's network in the `operator` field. Two values are accepted:

| `operator` | Network |
| --- | --- |
| `MTN` | MTN Mobile Money (MoMo) |
| `ORANGE` | Orange Money |

Which provider carries a given request is selected for you — you do not choose it, and it does not appear in the response. From your side there is only the `operator` value and the lifecycle above.

## Fees

When a collection settles `SUCCESS`, an **application fee** is taken before your balance is credited. The fee is computed from your merchant **charge tier**, which is either a percentage of the amount or a fixed amount, configured for your business.

By default the customer's debit covers the fee. Merchants flagged to absorb fees pay the fee themselves instead of passing it to the customer.

:::note
Fees are a settlement concept, not an API field. There is no public fee parameter beyond `amount` — you send the amount you want to charge, and the fee is applied against the settled funds per your tier. To model net proceeds, work from your configured charge tier.
:::

## Where to go next

| Page | What it covers |
| --- | --- |
| [Authentication](/en/payments/authentication) | The `X-API-Key` header, sandbox vs live keys, environment selection |
| [Create a payment](/en/api/direct-payments) | The `POST /v1/payments` request body and response, field by field |
| [Payment status](/en/api/direct-payments) | Retrieving and listing payments, the status enum, pagination |
| [Webhooks](/en/payments/webhooks) | `payment.success` / `payment.failed`, signing secrets, signature verification |
| [Testing](/en/payments/testing) | Sandbox keys, simulated outcomes, guaranteed success/failure test numbers |
| [Interactive reference](/en/api) | Try the three endpoints live against your key |

:::tip
New here? Start with [Authentication](/en/payments/authentication) to get a sandbox key, then run your first collection from [Create a payment](/en/api/direct-payments).
:::
