DÉVELOPPEURS

Documentation API
Paygride.

Tout ce qu'il faut pour intégrer Paygride dans ton produit en 10 minutes.

QUICKSTART

Trois étapes.

01
Crée une clé API
Depuis le dashboard, Paramètres → Développeurs. Choisis un mode test ou live. La clé secrète ne s'affiche qu'une fois.
02
Appelle POST /v1/links
Envoie un titre, une devise et au moins un réseau. Le serveur te retourne un slug et une URL partageable.
03
Partage l'URL retournée
Colle l'URL dans WhatsApp, email ou ton site. Paygride affiche les méthodes actives selon le pays de l'acheteur.
curl
curl https://app.paygride.com/api/v1/links \
  -X POST \
  -H "Authorization: Bearer sk_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Pack Premium",
    "currency": "XOF",
    "accepted_networks": ["mtn", "moov"],
    "amount": 5000
  }'
ENCAISSER

Le flux complet, de bout en bout.

Crée un lien, encaisse sur la page hébergée, sois notifié côté serveur.

1
POST /v1/links
Ton serveur crée le lien et reçoit une URL partageable.
2
Tu partages l'url
WhatsApp, email, ou redirection depuis ton site.
3
Le client paie
Page de paiement hébergée par Paygride, méthodes filtrées par pays.
4
payment.succeeded
Paygride POSTe l'event signé sur ton endpoint serveur.

1. Créer le lien — POST /v1/links

Renseigne au minimum un title, une currency et au moins un réseau dans accepted_networks. Glisse ton identifiant de commande dans external_reference : Paygride te le renvoie tel quel dans le webhook.

title
string
requis
≤ 120 caractères
currency
string
requis
ISO 4217 — XOF, XAF, NGN, GHS, KES, USD, EUR
accepted_networks
string[]
requis
≥ 1 réseau (mtn, moov, orange, wave, card…). Voir GET /v1/methods
amount
number
optionnel
Omis = montant libre. Entier pour XOF/XAF/NGN/GHS/KES
subtitle
string
optionnel
≤ 200 caractères
expires_at
string
optionnel
ISO 8601
status
string
optionnel
"active" (défaut) ou "draft"
external_reference
string
optionnel
Ton ID de commande/facture, renvoyé tel quel dans le webhook. ≤ 255
201 Created
{
  "id": "f3a1c0d2-…",
  "slug": "pack-premium-x4z9",
  "url": "https://app.paygride.com/pay/acme/pack-premium-x4z9",
  "title": "Pack Premium",
  "subtitle": null,
  "amount": 5000,
  "currency": "XOF",
  "status": "active",
  "accepted_networks": ["mtn", "moov"],
  "expires_at": null,
  "external_reference": "order_1234"
}

Partage urltelle quelle, ou redirige l'acheteur dessus. Avec un domaine personnalisé (Paramètres → Domaines), l'URL est servie depuis ton sous-domaine.

2. Confirmer le paiement — webhook payment.succeeded

Ne valide jamais un paiement sur la seule redirection navigateur : attends le webhook serveur-à-serveur. Enregistre ton endpoint dans Paramètres → Webhooks pour récupérer ton secret whsec_….

POST → ton endpoint
{
  "id": "evt_3a7e2c91b88f1d4ce5b0a223",
  "type": "payment.succeeded",
  "created": 1717160521,
  "data": {
    "transaction": {
      "id": "9b1c…",
      "reference": "KDT-ABC123",
      "provider_transaction_id": "fp_xyz",
      "status": "succeeded",
      "payment_link_slug": "pack-premium-x4z9",
      "external_reference": "order_1234"
    }
  }
}
node — vérifier la signature
import { createHmac, timingSafeEqual } from "node:crypto";

// secret  = whsec_… (dashboard → Paramètres → Webhooks)
// rawBody = corps BRUT de la requête (string) — surtout pas JSON.parse puis re-stringify
// header  = valeur du header X-Paygride-Signature, ex. "t=1717160521,v1=ab12…"
export function verifyPaygrideSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(
    header.split(",").map((kv) => kv.trim().split("=", 2)),
  );
  const ts = Number(parts.t);
  const v1 = parts.v1;
  if (!ts || !v1) return false;

  if (Math.abs(Date.now() / 1000 - ts) > 300) return false; // anti-replay 5 min

  const expected = createHmac("sha256", secret)
    .update(`${ts}.${rawBody}`)
    .digest("hex");

  return (
    expected.length === v1.length &&
    timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(v1, "hex"))
  );
}

Réconcilie sur external_reference (ton ID de commande) ou reference(l'ID Paygride). Réponds 2xxen moins de 10 s et traite l'event de façon idempotente (tu peux le recevoir plusieurs fois — l'idde l'event est stable).

ENDPOINTS

Référence des routes publiques.

Base URL : https://app.paygride.com/api/v1

GET
/v1/methods
Liste des méthodes de paiement actives par pays
GET
/v1/links
Liste paginée des liens de paiement
POST
/v1/links
Crée un nouveau lien de paiement
GET
/v1/links/{slug}
Récupère un lien par son slug
GET
/v1/transactions
Liste paginée des transactions
GET
/v1/transactions/{id}
Récupère une transaction par UUID
GET
/v1/events
Liste paginée des évènements (billetterie)
GET
/v1/payouts
Liste paginée des transferts sortants
POST
/v1/payouts
Crée un transfert sortant (cascade auto sur PSPs connectés)
GET
/v1/payouts/{id}
Détail d'un transfert + cascade des tentatives
AUTHENTIFICATION

Bearer token, sur chaque requête.

Toutes les requêtes nécessitent un header Authorization: Bearer <clé>. Les clés sont créées depuis le dashboard, en mode test ou live. La clé secrète n'est affichée qu'au moment de la création - copie-la, on ne la stocke pas en clair.

curl
curl https://app.paygride.com/api/v1/methods \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx"

Scopes

Chaque clé porte des scopes. read couvre les GET ; write est requis pour POST /v1/links et POST /v1/payouts. Un scope manquant renvoie 403.

Limites de débit

100 requêtes/min par clé, 200/min par IP. Au-delà, la requête est rejetée en 401 — espace tes appels en cas de pic.

ERREURS

Codes HTTP retournés.

400
Body ou paramètres invalides
401
Auth absente, invalide, clé révoquée/expirée, ou quota dépassé
403
Scope insuffisant (read/write) ou compte non vérifié (KYC) pour cette action
404
Ressource introuvable ou hors de ton organisation
422
Requête valide mais non traitable (ex. aucune passerelle ne couvre un payout)
500
Erreur interne Paygride

Les erreurs sont retournées au format { "error": "description courte" }.

WEBHOOKS SORTANTS

Sois notifié dès qu'un paiement aboutit.

Paygride POSTe un payload JSON signé HMAC SHA-256 sur ton URL à chaque event. Configure tes endpoints dans Paramètres → Webhooks.

Headers envoyés

Content-Type: application/json
User-Agent: Paygride-Webhook/1.0
X-Paygride-Signature: t=<ts>,v1=<sha256>
X-Paygride-Delivery-Id: <uuid>

La signature recompose <ts>.<raw_body> puis HMAC-SHA256 avec ton secret. Tolérance 5 min contre replay.

Events disponibles

payment.succeeded
Tx passe à succeeded
LIVE
payment.failed
Tx passe à failed
LIVE
payment.refunded
Remboursement traité
SOON
payout.processing
Payout envoyé au PSP
LIVE
payout.paid
Confirmé par le PSP
SOON
payout.failed
Tous les PSPs ont refusé
LIVE
ping
Test manuel depuis le dashboard
LIVE

Retry policy : 7 tentatives avec backoff exponentiel (1 min → 5 min → 30 min → 2 h → 12 h → 1 jour). Ton endpoint doit répondre 2xx en moins de 10 s. Au-delà, la delivery passe en abandoned (visible dans le dashboard).

ROADMAP

Bientôt disponible.

Endpoints et outils en cours de développement.

À VENIRPOST /v1/payments - session checkout one-shot
À VENIRGET/POST /v1/webhook_endpoints - CRUD endpoints par API (aujourd'hui dashboard only)
À VENIRWorker de retry/poll pour payouts (status PSP final automatique)
À VENIRSDK officiel Node.js et PHP
À VENIRPlugin WooCommerce

Référence complète sur GitHub.

Le fichier docs/PUBLIC_API.md est la source de vérité, mise à jour à chaque release.