Guides
Liens de paiement
Un lien de paiement est une page hébergée par MivaaPay, avec un montant et un libellé fixés d'avance. Vous le partagez — WhatsApp, e-mail, QR code sur une facture — et le client paie sans que vous ayez une ligne de front-end à écrire.
Utilisez POST /payments quand vous contrôlez le parcours (panier en ligne,
application). Utilisez un lien de paiement quand il n'y a pas de parcours à contrôler :
une facture à régler, une vente sur les réseaux sociaux, un encaissement en présentiel.
Créer un lien
curl -X POST https://api.mivaapay.com/api/v1/payment-links \
-H "Authorization: Bearer $MIVAAPAY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 15000,
"description": "Facture 2026-118 — prestation de conseil",
"type": "permanent"
}'
$link = Http::withToken(env('MIVAAPAY_SECRET_KEY'))
->post('https://api.mivaapay.com/api/v1/payment-links', [
'amount' => 15000,
'description' => 'Facture 2026-118 — prestation de conseil',
'type' => 'permanent',
])
->json('data');
// $link['url'] : l'adresse à partager
const res = await fetch('https://api.mivaapay.com/api/v1/payment-links', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MIVAAPAY_SECRET_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 15000,
description: 'Facture 2026-118 — prestation de conseil',
type: 'permanent'
})
});
const { data: link } = await res.json();
link = requests.post(
'https://api.mivaapay.com/api/v1/payment-links',
json={
'amount': 15000,
'description': 'Facture 2026-118 — prestation de conseil',
'type': 'permanent',
},
headers={'Authorization': f"Bearer {SECRET_KEY}"},
timeout=30,
).json()['data']
{
"success": true,
"data": {
"id": 412,
"url": "https://app.mivaapay.com/process-payment/a7Kd93Lm0P/x2b412",
"type": "permanent",
"amount": 15000,
"description": "Facture 2026-118 — prestation de conseil",
"max_uses": null,
"uses_count": 0,
"uses_left": null,
"starts_at": null,
"expires_at": null,
"created_at": "2026-08-05T11:02:38+00:00"
}
}
Le champ url est ce que vous partagez. Il est généré aléatoirement et n'est pas
devinable ; il n'est en revanche protégé par rien d'autre : quiconque l'a peut ouvrir la
page de paiement.
Deux types de liens
| Type | Comportement | Usage |
|---|---|---|
permanent |
Réutilisable sans limite de nombre. | Un lien de don, un tarif fixe affiché en boutique. |
limité |
Utilisable max_uses fois, puis épuisé. |
Une facture nominative (max_uses: 1), une place d'événement. |
limité, avec l'accent
Le type limité s'envoie littéralement "type": "limité". Envoyez le corps en
UTF-8 ; toute autre orthographe (limite, limited)
est rejetée avec un invalid_request. C'est une bizarrerie du contrat v1, que
nous ne pouvons pas corriger sans casser les intégrations existantes.
{
"amount": 15000,
"description": "Facture 2026-118",
"type": "limité",
"max_uses": 1,
"expires_at": "2026-09-01T23:59:59+00:00"
}
max_uses devient obligatoire dès que type vaut limité.
Pour un lien permanent, il est ignoré et la réponse renvoie max_uses: null.
Fenêtre de validité
starts_at et expires_at sont deux dates ISO-8601 optionnelles.
expires_at doit être postérieure à starts_at. Laisser les deux à
null donne un lien valable indéfiniment.
| Champ | Requis | Description |
|---|---|---|
amount |
oui | Montant que vous encaissez. Entre 1 et 99 999 999. |
description |
oui | Libellé affiché au client sur la page de paiement. 255 caractères maximum. |
type |
non | permanent (défaut) ou limité. |
max_uses |
oui* | *Requis si type vaut limité. Entier ≥ 1. |
starts_at |
non | Date d'ouverture du lien, format ISO-8601. |
expires_at |
non | Date de fermeture, postérieure à starts_at. |
Suivre l'usage d'un lien
uses_count compte les paiements aboutis, uses_left ce qu'il reste
(toujours null pour un lien permanent) :
curl https://api.mivaapay.com/api/v1/payment-links/412 \
-H "Authorization: Bearer $MIVAAPAY_SECRET_KEY"
curl "https://api.mivaapay.com/api/v1/payment-links?per_page=50" \
-H "Authorization: Bearer $MIVAAPAY_SECRET_KEY"
Encaissements issus d'un lien
Les paiements réglés via un lien remontent comme n'importe quel autre : ils apparaissent dans
GET /payments et déclenchent les mêmes webhooks payment.succeeded.
Branchez donc les webhooks avant de diffuser un lien, sinon vous
n'apprendrez les paiements qu'en consultant la liste.
POST /payment-links est refusé avec une clé sk_test_… : la page
hébergée est ouverte par le client sans clé API, rien ne permettrait de savoir qu'elle doit
simuler plutôt qu'encaisser. Validez vos encaissements avec POST /payments en
mode test, puis créez vos liens avec votre clé live.
Un lien ne peut pas être désactivé ni modifié par l'API — passez par le back-office. Il n'y a pas non plus de filtre permettant de retrouver directement les paiements issus d'un lien donné : si vous en avez besoin, générez un lien par facture et rapprochez sur le montant et la date.