Docs développeur

Docs développeur — QLOA Affiliation

Intégrer le tracking, envoyer des conversions, poser le snippet cookie côté produit. Toutes les routes ci-dessous vivent sur le domaine de la plateforme.

Lien de tracking — GET /r/{code}

Chaque affilié génère des liens de la forme ci-dessous. Le redirect est immédiat (302) vers l'URL cible avec ?ref={code} ajouté à la query existante ; le clic est enregistré en tâche asynchrone (IP/UA hashés, RGPD).

https://affiliation.antislash.studio/r/abc123
→ 302 https://votre-produit.com/pricing?ref=abc123

Snippet cookie first-party (à poser côté produit)

Lit le paramètre ?ref= à l'arrivée sur votre site et pose un cookie first-party (90 jours max recommandé), envoyé au moment du signup pour rattacher le nouveau client à l'affilié.

⚠️ RGPD/CNIL : les traceurs d'affiliation ne sont PAS exemptés de consentement (lignes directrices 2020-091/092). Déclenchez ce snippet UNIQUEMENT après consentement via votre CMP (catégorie marketing/affiliation), durée ≤ 13 mois. Fallback sans cookie : transmettez le ?ref= reçu dans la même session au signup, ou utilisez les codes promo (aucun traceur).
<script>
(function () {
  var params = new URLSearchParams(window.location.search);
  var ref = params.get('ref');
  if (ref) {
    var days = 60;
    var expires = new Date(Date.now() + days * 86400000).toUTCString();
    document.cookie = 'qaff_ref=' + encodeURIComponent(ref) + '; expires=' + expires + '; path=/; SameSite=Lax';
  }
})();
</script>

<!-- Au signup, envoyez la valeur du cookie qaff_ref dans votre payload -->
<!-- (customer_external_id / affiliate_code du POST /api/v1/conversions, voir plus bas) -->

Webhook conversions — POST /api/v1/conversions

Signale une conversion (vente, abonnement…) depuis votre backend. Idempotent sur external_id : rejouer le même événement renvoie {"status": "duplicate"} sans doublon.

Authentification — headers

  • X-Qaff-Token — le token d'endpoint fourni par votre org (page Settings → Webhooks)
  • X-Qaff-Timestamp — epoch seconds, tolérance ±300s
  • X-Qaff-Signature — HMAC-SHA256 hex de "{timestamp}.{corps brut}" avec votre secret

Corps de la requête (JSON)

{
  "external_id": "inv_8842",
  "program_id": "0c9e...-uuid-programme",
  "amount": 49.90,
  "currency": "EUR",
  "kind": "one_time",
  "occurred_at": "2026-08-20T10:00:00Z",
  "customer_email": "client@exemple.com",

  // Résolution de l'affilié — un seul suffit, ordre de priorité :
  "customer_external_id": "cust_123",  // 1. déjà attribué (customer-bound)
  "affiliate_code": "abc123",          // 2. code du lien /r/{code}
  "promo_code": "PARRAIN10"            // 3. code promo
}

Exemple curl

BODY='{"external_id":"inv_8842","program_id":"0c9e...","amount":49.90,"affiliate_code":"abc123"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | cut -d' ' -f2)

curl -X POST https://affiliation.antislash.studio/api/v1/conversions \
  -H "Content-Type: application/json" \
  -H "X-Qaff-Token: $WEBHOOK_TOKEN" \
  -H "X-Qaff-Timestamp: $TS" \
  -H "X-Qaff-Signature: $SIG" \
  -d "$BODY"

Exemple Python

import hashlib, hmac, json, time, requests

body = json.dumps({"external_id": "inv_8842", "program_id": "0c9e...", "amount": 49.90, "affiliate_code": "abc123"})
ts = str(int(time.time()))
signature = hmac.new(WEBHOOK_SECRET.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()

requests.post(
    "https://affiliation.antislash.studio/api/v1/conversions",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-Qaff-Token": WEBHOOK_TOKEN,
        "X-Qaff-Timestamp": ts,
        "X-Qaff-Signature": signature,
    },
)

Exemple Node.js

const crypto = require('crypto');

const body = JSON.stringify({ external_id: 'inv_8842', program_id: '0c9e...', amount: 49.90, affiliate_code: 'abc123' });
const ts = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac('sha256', WEBHOOK_SECRET).update(`${ts}.${body}`).digest('hex');

await fetch('https://affiliation.antislash.studio/api/v1/conversions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Qaff-Token': WEBHOOK_TOKEN,
    'X-Qaff-Timestamp': ts,
    'X-Qaff-Signature': signature,
  },
  body,
});

Réponses

  • 200 {"status": "created", "conversion_id": "..."}
  • 200 {"status": "duplicate"}
  • 401 token/signature invalide
  • 422 payload invalide
  • 404 programme ou affilié introuvable

Codes promo

Attribution sans cookie : un affilié peut avoir un code promo dédié (programme + affilié). Envoyez-le en promo_code dans le webhook conversions ci-dessus — la conversion sera attribuée même sans clic préalable sur un lien /r/{code}.

Import CSV

À venir — Lot 3

Import de conversions et d'affiliés depuis un export CSV (matching par code ou email) — utile pour rattraper l'historique ou migrer depuis un autre outil d'affiliation. Livré au Lot 3 (Espace éditeur).

Connecteur Pennylane

Zéro code produit : si votre facturation est réconciliée dans Pennylane (paiements GoCardless notamment), un poll quotidien détecte les factures payées des clients déjà mappés à un affilié (customer_mappings) et crée les conversions automatiquement. Les avoirs émis déclenchent un clawback sur la commission correspondante.

Configuration : votre token API Pennylane est renseigné par votre contact QLOA dans les réglages du connecteur (page Settings de votre org, disponible au Lot 5).