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

# Payment links

> Create checkout links you send to customers by WhatsApp, SMS, email or QR code.

A payment link is a PrimePay checkout address (`https://checkout.primepay.mw/l/7KQ2M9XW`) you send to a customer by WhatsApp, SMS, email or a QR code. The customer opens it, chooses Airtel Money, TNM Mpamba or PrimePay Wallet, and pays. These are the same links you make in the [dashboard](https://dashboard.primepay.mw/) under Payment links, and links made with the API show there too.

Each payment made through a link is an ordinary payment: you get the usual payment webhooks, and the money follows your account's normal settlement.

Creating a link moves no money, so these endpoints take no `Idempotency-Key`. Sending the same request twice makes two links; deactivate the one you don't want.

Aggregators make a link for a sub-merchant with `POST /v1/sub-merchants/{subMerchantCode}/payment-links`. The customer sees the sub-merchant's name, the sub-merchant is credited, and you keep the agreed fee. If the sub-merchant is later suspended or removed from your account, the link stops taking payments.

## Link status

| Status | Meaning |
| - | - |
| `active` | Can be opened and paid. |
| `inactive` | Deactivated by you. Can be reactivated. |
| `completed` | A `once` link that has been paid. Final. |
| `expired` | Its `expiresAt` has passed. Final. |

## Payment link errors

Validation errors include `error.field`, which names the field (for example `amount` or `items[1].unitAmount`).

| Code | Status | Meaning |
| - | - | - |
| `invalid_payment_link` | 400 | A field is missing or wrong. `error.field` names it and `error.message` says what to fix. |
| `amount_or_items` | 400 | Both `amount` and `items` were sent. Send one. |
| `invalid_usage` | 400 | `usage` isn't `many` or `once`. |
| `invalid_expires_in` | 400 | `expiresIn` isn't `never`, `24h`, `7d` or `30d`. |
| `use_sub_merchant_endpoint` | 400 | A sub-merchant or account was named in the body. The sub-merchant goes in the address; the account always comes from the API key. |
| `payment_link_refused` | 400 | The link can't be made right now, for example the account is disabled. |
| `sub_merchant_not_found` | 404 | No active sub-merchant with that account code is linked to your account (or the key's account isn't an aggregator). |
| `payment_link_not_found` | 404 | No link with that id on this account. |
| `payment_link_not_deactivated`, `payment_link_not_reactivated` | 409 | The link is completed, expired, or changed at the same moment. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.